2011-06-24 3 views
11

永続的/非永続的な属性を持つRailsモデルを想定すると、公開されているコードを見ると、さまざまなパターンが使用されます。Ruby/Railsモデル/コントローラのアソシエーション/アトリビュートを参照するときの*、self。*、@ *の相違点

たとえば、あるモデルから別のモデルへの関連付けがあるとします。 self.association_name@association_nameの違いは何ですか?。好ましい方法は何ですか?

モデル内のattr_accessor:attrで定義された非永続属性と同じです。両方の方法で参照することができます。self.attrおよび@attr好ましい方法は何ですか?

答えて

13

self.x/self.x=yは、常にメソッドコールです。

self.xself.__send__(:x)self.x = yのためだけの砂糖が本当にself.__send__(:x=, y)のためだけの砂糖である)

@xは、他の一方で、instance variableを指します。 ARのみ、その魔法の動作のためx/x=(方法ある)を定義するよう@xがARアソシエーションとを動作しません使用

。 (ARは基本的にただの類似した名前のインスタンス変数に無関係ある独自の内部のデータ構造を介してこれらの方法やルートで目的のアクセスを「キャプチャ」。)

attr_accessorは「両方の方法にアクセスする」ことができます理由との場合は、同じ名前のインスタンス変数を使用しています(その値をどこかに格納する必要があります)。 attr_accessor :xは、

def x; @x; end 
def x= (y); @x = y; end 

と同等であると考えてください。

+0

を参照してくださいattrを使用するためにあなたが優れている値を読み込むとき(self.attr=を呼び出す)属性を設定するためにのみ使用してください:私は実際に自己を使用する必要があります*それらを参照するために?この文脈で、自己を抜かすことの欠点は何ですか?* – Scholle

+2

@Scholle 'self.x = y'を使う必要があります。そうしないと、' y'の評価を 'x'ローカル変数に代入したいと思うでしょう。しかし、スコープ内に変数 'x'がないと仮定すると、' self.x'と 'x'はどちらも' x'メソッドを呼び出します。この場合、「自己」を省略することを好む人もいます(私はそうです)。大きな問題は、一貫性があること*です。 –

6

ほとんどの場合、@attrの代わりにattrを使用することをお勧めします。これは、メソッドattrが存在しない場合、属性を設定することが多いためです。例えば

このモデルのために:私は、このオブジェクトのメソッドtotalを呼び出していなかった場合、私は方法taxes@total代わりのtotalを使用した場合

model Order 
    have_many :items 

    def total 
    @total ||= items.collect(&:price).sum 
    end 

    def taxes 
    @taxes ||= total * 0.10 
    end 
end 

このモデルは、Vellのに動作しますが、Calculが失敗しましたでしょう前。

@pstが指摘しているように、@association_nameは関連付けには使用できませんので、方法association_nameを使用する必要があります。またself.attr

は、組合について this article : When to used self Rails model

+0

+1私の回答を四捨五入したもの:p –

+0

あなたが投稿した記事では、「属性と同じ名前のローカル変数を使用しないでください」と記載されています。これは、基本的に同じ名前のローカル変数を持っているかどうかにかかわらず、新しい属性を導入した後に毎回コードをチェックする必要があることを意味します。たとえば、def start_time ... end(getter)とdef start_time ... end(setter)の2つのメソッドがあります。この記事では、start_timeというローカル変数(時間の計算など)を使用するのは不適切です。 – Scholle

+0

この文の正確な感覚は、たとえば '@ total'のような属性を持つ場合、このクラスのメソッドで' total'という名前の変数を使うべきではありません。これは 'total'をa変数 'total'を使用することと' @total'のアクセサーを呼び出すこと(既存の場合)とを混同します。だからあなたは正しいです、クラスに 'start_time'メソッドがある場合は、' start_time'という変数を使うべきではありませんが、必要に応じて '@ start_time'という属性を使って**値を保存することができます** –

関連する問題