80

質問:Railsのモデルで自分自身を使用する必要があるのはいつですか?

モデルの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の値は変更されず、サイレントに失敗します。誰かが説明できますか?

重複は見つかりませんが、誰かが見つけた場合は問題ありません。

4

4 に答える 4

76

メソッドを呼び出しているインスタンスでアクションを実行するときは、selfを使用します。

このコードで

class SocialData < ActiveRecord::Base
  def set_active_flag(val)
    active_flag = val
    save!
  end
end

active_flagと呼ばれる新しいスコープのローカル変数を定義し、渡された値に設定します。これは何にも関連付けられていないため、メソッドが存在しなかったように終了するとすぐに破棄されます。

self.active_flag = val

ただし、新しい変数ではなく、active_flagと呼ばれる独自の属性を変更するようにインスタンスに指示します。それが機能する理由です。

于 2012-05-29T19:09:25.943 に答える
70

これは、スコープが原因で発生します。メソッド内にいて、次のような新しい変数を設定しようとした場合:

class SomeData < ActiveRecord::Base
  def set_active_flag(val)
    active_flag = val
  end
end

set_active_flag内に存在する新しい変数を作成しています。実行が完了するとすぐに消え、self.active_flag(実際のインスタンス変数)は変更されません。

ただし(これは私にとって混乱の原因でした):次のように、rubyでインスタンス変数を読み取ろうとすると:

class SomeData < ActiveRecord::Base
  def whats_my_active_flag
    puts active_flag
  end
end

実際にself.active_flag(実際のインスタンス変数)が返されます。


理由は次のとおりです。

Rubyは、戻りを回避するためにできることを実行しますnil

  1. 最初に「active_flagの範囲内に存在しますwhats_my_active_flagか? 」と尋ねます。
  2. 検索して答えが「いいえ」であることに気付くと、SomeDataのインスタンスに1レベル上にジャンプします。
  3. それは再び同じことを尋ねます:「active_flagこの範囲内に存在しますか?
  4. 答えは「うん」なので、「私はあなたのために何かを手に入れました」と表示され、それが返されます!

ただし、active_flag内で定義しwhats_my_active_flag、それを要求すると、次の手順が再度実行されます。

  1. active_flagの範囲内に存在しますwhats_my_active_flagか?
  2. 答えは「うん」なので、その値を返します

いずれの場合も、明示的に指示しない限り、の値は変更されません。self.active_flag

この振る舞いを説明する簡単な方法は、「あなたを失望させたくない」というnilことです。そのため、できる限りのことを見つけるのが最善です。

同時に、「変更するつもりのないデータを台無しにしたくない」ので、インスタンス変数自体を変更しません。

お役に立てれば!

于 2013-12-23T06:31:57.867 に答える
2

これは、setterメソッドを使用していて、新しい変数のスコープを設定していないことを確認するためです。これはRubyとARの使用法の詳細であり、多くの場合、人をつまずかせます(もう1つは、インスタンス変数の(誤)使用です)。

すでにupdate_attributesがあることに注意してください!私は抽象化したいという願望を理解していますが。

トグルもあります!、フラグへのインターフェイスによっては、さらに良い場合があります。

于 2012-05-29T19:10:13.563 に答える
0

active_flag = valあなたがローカル変数を定義していると思ってrubyを使うとき、最良の方法はself.active_flag = val、もしあなたがそれを手に入れたら、それもうまくいくことを知っていることを願っていますsend(:active_flag=, val)

于 2017-10-30T15:30:51.720 に答える