2011-08-23 86 views
5

我有这样的:Ruby中的方法的静态局部变量?

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可访问从任何地方,但该方法, 这可能与红宝石?

+2

简短的回答是否定的,Ruby中没有'static'这样的东西。为什么不让数据库处理您的自动递增键? – Emily

+0

因为这是一种为Rspec测试生成有效属性的方法,有些事情必须是唯一的。 – Zequez

回答

6

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

我认为你真正在这里寻找的是工厂。尝试使用诸如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中有很多更多功能的说明,以及如何将工厂添加到项目中的说明。

+0

谢谢!我会明确地检查那个宝石! ^^ – Zequez

0

Ruby的唯一变量是局部变量,实例变量,类变量和全局变量。它们都不符合你的要求。

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

4

我会用一个实例变量:

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

您可以使用封闭:

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=>"[email protected]"} 
valid_attributes.call #=> {:email=>"[email protected]"} 

这样user_id不会被外界访问。

7

这是封闭案例。试试这个

 
lambda { 
    user_id = 0 

    self.class.send(:define_method, :valid_attributes) do 
    user_id += 1 
    { :email => "some_#{user_id}@thing.com" } 
    end 

}.call 

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

+0

我在你的代码后面加了两个'p valid_attributes',但是我得到了'Error NoMethodError:undefined method'+'for nil:NilClass'。我猜'def'里面的'user_id'是一个初始化为'nil'的局部变量。也许你可以用另一种方式使用闭包。 :) –

+0

嗨索尼,我忘了def。我已经将它改为define_method,所以它现在应该可以访问user_id。这种方法在lambda中定义的其他方法也可以共享user_id变量。 – RubyFanatic

+1

好的,但你必须使用'self.class.send:define_method,:valid_attributes',因为'define_method'是一个私有类方法。无论如何,我更喜欢你的解决方案[我的](http://stackoverflow.com/questions/7168400/static-local-variables-for-methods-in-ruby/7169076#7169076),因为在我的情况下'valid_attributes'是一个proc(必须在1.8.7中用'call'或'[]'调用),在你的情况下它是一个真正的方法。 –