2009-07-28 8 views
0

私は問題を解決するために出発しました。属性または関係を不変にする必要があるかもしれません。つまり、属性が書き込まれると永遠に書き出されます。それは関係のために動作しませんでしたようattr_readonlyは、適切ではなかったので、私はここにコンセプトを証明しようとした:不変のアクティブなレコードの関係と属性(セッター)

http://pastie.org/562329

これは私のテストを示し、実装例(理想的に私はモジュールに移動するだろうと) - これがリレーションシップ・セッターを過負荷にする許容可能な方法であるかどうかは分かりませんが、テストを拡大して現在はhttp://pastie.org/562417と読んでいますが、これは過度の可能性がありますが、customer_idがcustomerしかし、私は訂正されること以上に幸せになるでしょう!

答えて

3

私はそれを試していないが、私はupdate_attribute(:customer_id => 1)は、いくつかのケースで破ると思います。また、私は本当に属性設定子をオーバーライドする考え方が嫌いです。

より良い(IMHO)アプローチは、「before_update」を無効にし、何かが変更された場合は無効にすることです。これはDirtyモジュールを使用して行うことができます。チェックアウトこの:

私はこれをテストしていませんが、それはの行の何かを行く:

class Order < ActiveRecord::Base 
    IMMUTABLE = %w{customer_id notes} 

    before_save do |record| 
    return false if IMMUTABLE.any? { |attr| record.changed.has_key?(attr) } 
    end 
end 

はもちろん、あなたがIMMUTABLE処理する方法の良いアイデアを持っています。これをモジュールに入れると、before_saveはModule#includedフックにある必要があります

+0

Stefan、属性設定子のオーバーロードが悪い、または間違っているという証拠はありますか?私はあなたの答えに同意する、それは私よりもはるかにクリーンですが、私はまた、これが好ましい方法であることを示す文書を見つけることができません! –

+0

私はそれが悪いか病気のアドバイスだとは思わない - 私はちょうどそれが好きではない。あなたが関係を持っているときはちょっと混乱します(あなたはfoo =とfoo_id =の両方をオーバーライドする必要があります)。また、私が考えることができるものは、オブザーバーや他のアプローチによって達成することができます。 さらに、特定のケースでは、あなたのソリューションをrecord.name << "something"でチェックしたいかもしれません。それは私の手を迂回し、あなたがセッターを呼び出すのではなく、その場所の属性を変更するので、オーバーライドするname =をバイパスします。 –

+0

[この回答](http://stackoverflow.com/questions/14779879/prevent-change-of-one-field-in-rails-model/14781183#14781183)には、変更された属性のレール検証を使用した1つまたは2つの例があります。 – twelve17

-1

最初の書き込みの後、メソッドがno-opとして再定義されるように、setterメソッドを定義することができます。

class Order < ActiveRecord::Base 
    def customer= c 
    if c 
     super 
     class << self 
     def customer= c 
     end 
     end 
    end 
    end 
end 
+0

私はその考えを嫌いです。それ自体の利益のためにあまりにも賢いから離れて、それはちょうどうまくいかない。オブジェクトをリロードすると、シングルトンクラスが失われ、もう一度オーバーライドできます。さらに、これはupdate_attributesに気づかれません。 –

関連する問題