2011-08-23 8 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はどこからでもアクセスできるようにしたいが、 はRubyで可能ですか?

+2

短い答えはいいえ、Rubyには「静的」というものはありません。なぜあなたの自動インクリメントキーをデータベースで処理させないのですか? – 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.createFactory.buildを使用することができます

Factory.attributes_for(:model) 

を使用することができます。

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 

ラムダのすべてをラップすると、ラムダ内で定義された変数がスコープ内にのみ存在することができます。他のメソッドも追加できます。がんばろう!

+0

あなたのコードに2つの 'p valid_attributes'を追加してみましたが、' Error NoMethodError:undefined method '+' for nil:NilClass'があります。私は 'def'の' user_id'は 'nil'で初期化されたローカル変数だと思います。たぶん別の方法でクロージャーを使うことができます。 :) –

+0

こんにちはソニー、私はデフを忘れてしまった。私はすでにdefine_methodに変更していますので、今はuser_idにアクセスできるはずです。このようにラムダ内で定義された他のメソッドは、user_id変数を共有することもできます。 – RubyFanatic

+1

'define_method'はプライベートクラスメソッドなので、' self.class.send:define_method、:valid_attributes'を使う必要があります。とにかく、あなたの解決策は私の[mine](http://stackoverflow.com/questions/7168400/static-local-variables-for-methods-in-ruby/7169076#7169076)です。なぜなら、私の場合は 'valid_attributes'がproc(1.8.7では 'call'や '[]'で呼び出さなければなりません)、あなたの場合は本物のメソッドです。 –

関連する問題