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

时间:2011-08-23 22:41:16

标签: ruby variables methods static local

我有这个:

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

我不希望{@ 1}}可以从任何地方访问,但该方法, 这可能与Ruby有关吗?

5 个答案:

答案 0 :(得分:8)

这是一个封闭案例。试试这个

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中定义的变量仅存在于范围内。您也可以添加其他方法。祝你好运!

答案 1 :(得分: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中更多功能的说明,以及如何将工厂添加到项目中的说明。

答案 2 :(得分:5)

您可以使用闭包:

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无法在外部访问。

答案 3 :(得分:4)

我使用了一个实例变量:

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

答案 4 :(得分:0)

Ruby唯一的变量是局部变量,实例变量,类变量和全局变量。它们都不适合你所追求的目标。

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