2017-02-16 2 views
0

Numberplateのネストされた属性を持つGuestというモデルがあります。ネストされた属性の作成を伴うモデルは、before_validationとbefore_saveの間のアソシエーションタイプ属性を変更します。

Guestは、STI(単一テーブル継承)を採用し、Personから継承します。余分なクエリや他のテーブルへの参加を避けるために、テーブルのperson_typeというフィールドに人のタイプを保存します。そうすれば、私はどのナンバープレートが、人テーブルに参加する必要なく、ゲストによって所有されているのか知ることができます。

この設定のため、Numberplate(別の人物タイプがあります)に正しいperson_typeを手動で設定する必要があります。実際の実装はもう少し汎用的であるが、それはこれに沸く

before_validation do 
    self.person_type = self.person.type 
end 

:私はNumberplateモデルにbefore_validationコールバックとしてこれを実装しました。 予想通り今私は、コンソールでこのすべての作品を1回の呼び出しでGuestNumberplateを作成します。

Numberplate.new({person: Guest.new({company: Company.first}), plate: 'EFEF98'})

person_typeNumberplateインスタンス上では正しく"Guest"に設定されています。

ネストされた属性でGuestNumberplateを1回のリクエストで作成できるAPIエンドポイントがある場合、問題が発生します。奇妙なことは、person_type"Person'として格納され、期待通りには"Guest"ではないということです。私はちょっとデバッグし、person_typebefore_validationコールバックで正しく設定されますが、そのコールバックとbefore_saveコールバックの間でが突然"Person"に変更されました。 私はperson_typeセッターを無効にしようとしました。奇妙なことは、2人のActiveRecordコールバックの間にsetterが呼び出されないということです。

この動作がどのように導入されたのか、これがRailsコアのどこかのバグか、何かを考慮していないかどうか少し気が散っています。私の現在の回避策は、before_saveコールバックでperson_typeを設定することですが、これは最適な解決策ではありません。

関連モデル:

class Guest < Person 
    accepts_nested_attributes_for :numberplates 
end 

class Numberplate < ApplicationRecord 
    before_validation do 
     self.person_type = self.person.type 
    end 

    after_validation do 
     # person_type is correctly set to "Guest" 
     puts self.inspect 
    end 

    before_create do 
     # person_type is now suddenly set to "Person" 
     puts self.inspect 
    end 
end 
+0

[アソシエーションコールバック](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Association+callbacks)を試してください。 – max

+0

@maxが試しただけで、同じ振る舞いを表示します – edwardmp

+0

私の側にカスタムコードがなくても、person_type列をPersonに設定しているものがあります。奇妙な。 – edwardmp

答えて

0

は、だから私はそれを考え出しました。私はこれを持っていたPersonクラスで

has_many :numberplates, as: :person, inverse_of: :person 

as: :person部分があることと、この動作を導入してはなりません。多形性からSTIへの早期移行のためにそこにあったため、忘れ去られた残り物でした。一度これを削除すると、すべてが期待通りに機能しました。

関連する問題