質問:Railsのモデルでselfを使用する必要があるのはいつですか?
モデルの1つにset
メソッドがあります。
class SomeData < ActiveRecord::Base
def set_active_flag(val)
self.active_flag = val
self.save!
end
end
これを行うと、すべてが正常に機能します。ただし、これを行うと:
class SomeData < ActiveRecord::Base
def set_active_flag(val)
active_flag = val
save!
end
end
Active_flagの値は変更されず、サイレントに失敗します。誰か説明できますか?
重複を見つけることはできませんが、誰かがそれを見つけたとしてもそれは問題ありません。
メソッドを呼び出しているインスタンスでアクションを実行するときは、selfを使用します。
このコードで
class SocialData < ActiveRecord::Base
def set_active_flag(val)
active_flag = val
save!
end
end
Active_flagと呼ばれるまったく新しいスコープのローカル変数を定義し、渡された値に設定します。何にも関連付けられていないため、メソッドが存在しなかったように終了するとすぐに破棄されます。
self.active_flag = val
ただし、真新しい変数ではなく、active_flagと呼ばれる独自の属性を変更するようインスタンスに指示します。それが動作する理由です。
これは、スコーピングが原因で発生します。メソッドの内部にいるときにsetのような新しい変数をしようとすると:
class SomeData < ActiveRecord::Base
def set_active_flag(val)
active_flag = val
end
end
Set_active_flag内に存在する新しい変数を作成しています。実行が完了するとすぐに消え、self.active_flag
(実際のインスタンス変数)は変更されません。
[〜#〜] however [〜#〜](これは私にとって混乱の原因でした):readのようなRubyのインスタンス変数:
class SomeData < ActiveRecord::Base
def whats_my_active_flag
puts active_flag
end
end
実際にself.active_flag
(実際のインスタンス変数)が返されます。
理由:
Rubyはnil
を返さないようにできることをします。
active_flag
はwhats_my_active_flag
のスコープ内に存在しますか?active_flag
はこのスコープ内に存在しますか?ただし、active_flag
内でwhats_my_active_flag
を定義し、それを要求した場合は、再度手順を実行します。
active_flag
はwhats_my_active_flag
のスコープ内に存在しますか?どちらの場合も、明示的に指示しない限り、changeself.active_flag
の値にはなりません。
この動作を説明する簡単な方法は、「あなたを失望させたくない」とnil
を返すことです。
同時に、「変更するつもりのないデータを台無しにしたくない」ので、インスタンス変数自体を変更しません。
お役に立てれば!
Setterメソッドを使用していることを確認し、新しい変数をスコープしないようにします。 RubyとARの使用法の詳細は、しばしば人をつまずかせます(もう1つは、インスタンス変数の(誤った)使用法です)。
pdate_attributes! がすでに存在することに注意してください。
また、 toggle! もあります。これは、フラグへのインターフェースに応じて、さらに良い場合があります。
active_flag = val
Rubyがローカル変数を定義していると考えた場合、最良の方法はself.active_flag = val
です。もし手に入れたら、send(:active_flag=, val)
がも動作します。