web-dev-qa-db-ja.com

Rails:has_many through polymorphicassociation-これは機能しますか?

Personは多くのEventsを持つことができ、各Eventは1つのポリモーフィックなEventableレコードを持つことができます。 PersonレコードとEventableレコードの関係を指定するにはどうすればよいですか?

これが私が持っているモデルです:

class Event < ActiveRecord::Base
  belongs_to :person
  belongs_to :eventable, :polymorphic => true
end

class Meal < ActiveRecord::Base
  has_one :event, :as => eventable
end

class Workout < ActiveRecord::Base
  has_one :event, :as => eventable
end

主な質問はPersonクラスに関するものです。

class Person < ActiveRecord::Base
  has_many :events
  has_many :eventables, :through => :events  # is this correct???
end

上記のようにhas_many :eventables, :through => :eventsと言いますか?

または、次のようにすべてを綴る必要がありますか?

has_many :meals, :through => :events
has_many :workouts, :through => :events

私が求めていることを達成するためのより簡単な方法を見つけたら、私はすべての耳です! :-)

39
Finch

あなたはしなければならない:

class Person < ActiveRecord::Base
  has_many :events
  has_many :meals, :through => :events, :source => :eventable,
    :source_type => "Meal"
  has_many :workouts, :through => :events, :source => :eventable,
    :source_type => "Workout"
end

これにより、次のことが可能になります。

p = Person.find(1)

# get a person's meals
p.meals.each do |m|
  puts m
end

# get a person's workouts
p.workouts.each do |w|
  puts w
end

# get all types of events for the person
p.events.each do |e|
  puts e.eventable
end
69
Rob Sobers

これの別のオプションは、単一テーブル継承(STI)またはマルチテーブル継承(MTI)パターンを使用することですが、これにはActiveRecord/DBテーブルのやり直しが必要ですが、これは、初めて設計している他の人がこれを見つけるのに役立つ場合があります。

これがRails 3+のSTIメソッドです:あなたのEventableコンセプトはクラスになり、type列(Railsが自動的に入力されます)。

class Eventable < ActiveRecord::Base
  has_one :event
end

次に、AR :: Baseの代わりにEventableから他の2つのクラスinherit

class Meal < Eventable
end

class Workout < Eventable
end

また、イベントオブジェクトは基本的に同じですが、ポリモーフィックではありません。

class Event < ActiveRecord::Base
  belongs_to :person
  belongs_to :eventable
end

これは、これまでにこれを見たことがなく、注意しない場合、他のレイヤーのいくつかをより混乱させる可能性があります。たとえば、ルートで両方のエンドポイントを使用できるようにすると、/meals/1/eventable/1で単一のMealオブジェクトにアクセスでき、継承をプルするときに使用しているクラスを認識する必要があります。オブジェクト(ヒント:becomesmethod は、デフォルトのRails動作)をオーバーライドする必要がある場合に非常に便利です。

しかし、私の経験では、これはアプリの拡張に伴う責任のはるかに明確な説明です。考慮すべき単なるパターン。

1
toobulkeh