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

时间:2020-12-14 03:12:40

I have this:

我有这个:

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

For Rspec testing right? But I would like to do something like this:

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

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

I don't want user_id to be accessible from anywhere but that method, is this possible with Ruby?

我不希望user_id可以从任何地方访问,但是这个方法,这可以用Ruby吗?

5 个解决方案

#1


6  

This answer is a little larger in scope than your question, but I think it gets at the root of what you're trying to do, and will be the easiest and most maintainable.

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

I think what you're really looking for here is factories. Try using something like factory_girl, which will make a lot of testing much easier.

我认为你真正想要的是工厂。尝试使用像factory_girl这样的东西,这将使很多测试变得更容易。

First, you'd set up a factory to create whatever type of object it is you're testing, and use a sequence for the email attribute:

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

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

Then, when you need valid attributes, you can use

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

Factory.attributes_for(:model)

You can also use Factory.create and Factory.build to create saved and unsaved instances of the model.

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

There's explanation of a lot more of the features in the getting started document, as well as instructions on how to add factories to your project.

有关入门文档中的更多功能的说明,以及有关如何向项目添加工厂的说明。

#2


8  

This is a closure case. Try this

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

lambda {
  user_id = 0

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

}.call

Wrapping everything in lambda allows the variables defined within lambda to only exist in the scope. You can add other methods also. Good luck!

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

#3


5  

You can use a closure:

你可以使用一个闭包:

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"}

This way user_id won't be accessible outside.

这样,user_id将无法在外部访问。

#4


4  

I'd use an instance variable:

我使用了一个实例变量:

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

#5


0  

The only variables Ruby has are local variables, instance variables, class variables and global variables. None of them fit what you're after.

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

What you probably need is a singleton that stores the user_id, and gives you a new ID number each time. Otherwise, your code won't be thread-safe.

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

#1


6  

This answer is a little larger in scope than your question, but I think it gets at the root of what you're trying to do, and will be the easiest and most maintainable.

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

I think what you're really looking for here is factories. Try using something like factory_girl, which will make a lot of testing much easier.

我认为你真正想要的是工厂。尝试使用像factory_girl这样的东西,这将使很多测试变得更容易。

First, you'd set up a factory to create whatever type of object it is you're testing, and use a sequence for the email attribute:

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

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

Then, when you need valid attributes, you can use

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

Factory.attributes_for(:model)

You can also use Factory.create and Factory.build to create saved and unsaved instances of the model.

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

There's explanation of a lot more of the features in the getting started document, as well as instructions on how to add factories to your project.

有关入门文档中的更多功能的说明,以及有关如何向项目添加工厂的说明。

#2


8  

This is a closure case. Try this

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

lambda {
  user_id = 0

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

}.call

Wrapping everything in lambda allows the variables defined within lambda to only exist in the scope. You can add other methods also. Good luck!

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

#3


5  

You can use a closure:

你可以使用一个闭包:

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"}

This way user_id won't be accessible outside.

这样,user_id将无法在外部访问。

#4


4  

I'd use an instance variable:

我使用了一个实例变量:

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

#5


0  

The only variables Ruby has are local variables, instance variables, class variables and global variables. None of them fit what you're after.

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

What you probably need is a singleton that stores the user_id, and gives you a new ID number each time. Otherwise, your code won't be thread-safe.

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