Ruby中方法的静态局部变量?

Posted

技术标签:

【中文标题】Ruby中方法的静态局部变量?【英文标题】:Static local variables for methods in Ruby? 【发布时间】:2011-11-02 08:40:48 【问题描述】:

我有这个:

def valid_attributes
   :email => "some_#rand(9999)@thing.com" 
end

Rspec 测试对吗?但我想做这样的事情:

def valid_attributes
  static user_id = 0
  user_id += 1
   :email => "some_#user_id@thing.com" 
end

我不希望 user_id 可以从除该方法之外的任何地方访问, Ruby 可以做到这一点吗?

【问题讨论】:

简短的回答是否定的,Ruby 中没有 static 这样的东西。为什么不让数据库处理你的自增键呢? 因为它是一种为Rspec测试生成有效属性的方法,有些东西必须是唯一的。 【参考方案1】:

这是一个结案案例。试试这个

拉姆达 用户 ID = 0 self.class.send(:define_method, :valid_attributes) 做 用户 ID += 1 :email => "some_#user_id@thing.com" 结尾 。称呼

在 lambda 中包装所有内容允许在 lambda 中定义的变量仅存在于作用域中。您也可以添加其他方法。祝你好运!

【讨论】:

我在你的代码后面加了两个p valid_attributes,但我得到了Error NoMethodError: undefined method '+' for nil:NilClass。我猜user_id 里面的def 是一个初始化为nil 的局部变量。也许你可以用另一种方式使用闭包。 :) 嗨索尼,我忘记了 def。我已经将它更改为define_method,所以它现在应该能够访问user_id。以这种方式在 lambda 中定义的其他方法也可以共享 user_id 变量。 好的,但是你必须使用self.class.send :define_method, :valid_attributes,因为define_method是一个私有类方法。无论如何,我更喜欢您的解决方案而不是 mine,因为在我的情况下,valid_attributes 是一个过程(在 1.8.7 中必须使用 call[] 调用),而在您的情况下,它是一种真正的方法。 【参考方案2】:

这个答案的范围比你的问题要大一些,但我认为它是你想要做的事情的根源,并且将是最简单和最可维护的。

我认为您在这里真正寻找的是工厂。尝试使用 factory_girl 之类的东西,这将使很多测试变得更加容易。

首先,您将设置一个工厂来创建您正在测试的任何类型的对象,并为电子邮件属性使用序列:

FactoryGirl.define do
  factory :model do
    sequence(:email) |n| "person#n@example.com" 
    # include whatever else is required to make your model valid
  end
end

然后,当你需要有效的属性时,你可以使用

Factory.attributes_for(:model)

您还可以使用Factory.createFactory.build 创建模型的已保存和未保存实例。

getting started document 中有更多功能的解释,以及如何将工厂添加到项目的说明。

【讨论】:

谢谢!我会明确地检查那个宝石! ^^【参考方案3】:

你可以使用闭包:

def validator_factory
  user_id = 0
  lambda do
    user_id += 1
     :email => "some_#user_id@thing.com" 
  end
end

valid_attributes = validator_factory

valid_attributes.call  #=>  :email=>"some_1@thing.com"
valid_attributes.call  #=>  :email=>"some_2@thing.com"

这样user_id 将无法在外面访问。

【讨论】:

【参考方案4】:

我会使用实例变量:

def valid_attributes
  @user_id ||= 0
  @user_id += 1
   :email => "some_#@user_id@thing.com" 
end

【讨论】:

【参考方案5】:

Ruby 仅有的变量是局部变量、实例变量、类变量和全局变量。它们都不适合你的追求。

您可能需要一个存储 user_id 并每次都为您提供新 ID 号的单例。否则,您的代码将不是线程安全的。

【讨论】:

以上是关于Ruby中方法的静态局部变量?的主要内容,如果未能解决你的问题,请参考以下文章

java中静态成员变量、实例变量、局部变量何时创建、何时销毁?

Java中成员变量局部变量全局变量静态变量成员变量

Java中成员变量局部变量全局变量静态变量成员变量

Java 局部变量实例变量类变量(静态变量)区别

为啥你可以在函数中使用另一种方法而不是赋值运算符来更改 Ruby 中局部变量的值?

java中静态变量的默认值是0?