14

has_manyRuby on Rails を使用して、所有者が常に既知であるが、関連付け内の項目が所有者の列で指定されたポリモーフィック (ただし同種) 型になるポリモーフィックな関係を実現するにはどうすればよいですか? たとえば、Producerクラスのhas_many製品が生産者のインスタンスに、実際には多くの自転車、アイスキャンディー、または靴ひもがあるとします。各製品クラス (自転車、ポプシクルなど) にプロデューサーとの関係を簡単に持たせることができますがbelongs_to、プロデューサー インスタンスが与えられた場合、それらがさまざまなタイプ (プロデューサー インスタンスごと) である場合、どのように製品のコレクションを取得できますか?

Rails のポリモーフィックな関連付けにより、プロデューサーは多くの製品に属することができますが、関係を逆にする必要があります。例えば:

class Bicycle < ActiveRecord::Base
  belongs_to :producer
end

class Popsicle < ActiveRecord::Base
  belongs_to :producer
end

class Producer < ActiveRecord::Base
  has_many :products, :polymorphic_column => :type # last part is made-up...
end

したがって、私の Producer テーブルには既に、いくつかの製品クラス (自転車、ポプシクルなど) に対応する「タイプ」列がありますが、どうすれば Rails で次のようなことができるようになります:

>> bike_producer.products
#=> [Bicycle@123, Bicycle@456, ...]
>> popsicle_producer.products
#=> [Popsicle@321, Popsicle@654, ...]

これが明らかであるか、よくある繰り返しである場合は申し訳ありません。私はそれを簡単に達成するのに驚くほど苦労しています。

4

5 に答える 5

6

製品ではなく、プロデューサーで STI を使用する必要があります。このようにして、プロデューサーのタイプごとに異なる動作を行いますが、単一のproducersテーブルで行います。

(ほぼ) ポリモーフィズムはまったくありません!

class Product < ActiveRecord::Base
  # does not have a 'type' column, so there is no STI here,
  # it is like an abstract superclass.
  belongs_to :producer
end

class Bicycle < Product
end

class Popsicle < Product
end

class Producer < ActiveRecord::Base
  # it has a 'type' column so we have STI here!!
end

class BicycleProducer < Producer
  has_many :products, :class_name => "Bicycle", :inverse_of => :producer
end

class PopsicleProducer < Producer
  has_many :products, :class_name => "Popsicle", :inverse_of => :producer
end
于 2012-09-27T22:12:01.233 に答える
2

フォーマットしてください

class Bicycle < ActiveRecord::Base 
  belongs_to :bicycle_obj,:polymorphic => true 
end 

class Popsicle < ActiveRecord::Base
  belongs_to :popsicle_obj , :polymorphic => true 
end 

class Producer < ActiveRecord::Base 
  has_many :bicycles , :as=>:bicycle_obj 
  has_many :popsicle , :as=>:popsicle_obj 
end 

このコードを使用します。何か問題がある場合は、コメントを残してください。

于 2010-07-10T17:28:43.313 に答える
1

これが私が現在使用している回避策です。実際のActiveRecord::Associationsから取得する便利なメソッド(収集操作)は提供されませんが、特定のプロデューサーの製品のリストを取得する方法は提供されます。

class Bicycle < ActiveRecord::Base
  belongs_to :producer
end

class Popsicle < ActiveRecord::Base
  belongs_to :producer
end

class Producer < ActiveRecord::Base
  PRODUCT_TYPE_MAPPING = {
    'bicycle' => Bicycle,
    'popsicle' => Popsicle
  }.freeze
  def products
    klass = PRODUCT_TYPE_MAPPING[self.type]
    klass ? klass.find_all_by_producer_id(self.id) : []
  end
end

もう1つの欠点は、型文字列から型クラスへのマッピングを維持する必要があることですが、それは自動化できます。ただし、このソリューションは私の目的には十分です。

于 2010-07-11T06:15:30.187 に答える
0

Rails では、ポリモーフィック アソシエーションが十分に文書化されていないことがわかりました。単一テーブルの継承スキーマがあり、これが最も多くのドキュメントを取得していますが、単一テーブルの継承を使用していない場合は、情報が不足しています。

:polymorphic => true オプションを使用して、 belongs_to 関連付けを有効にすることができます。ただし、単一テーブルの継承を使用していない限り、has_many アソシエーションは機能しません。これは、外部キーを持つ可能性のあるテーブルのセットを知る必要があるためです。

(私が見つけたものから)、きれいな解決策は、基本クラスのテーブルとモデルを持ち、基本テーブルに外部キーを持つことだと思います。

create_table "products", :force => true do |table|
    table.integer  "derived_product_id"
    table.string   "derived_product_type"
    table.integer  "producer_id"
  end

  class Product < ActiveRecord::Base
    belongs_to :producer
  end

  class Producer < ActiveRecord::Base
    has_many :products
  end

次に、Production オブジェクトのプロデューサーについては、products.products.derived_products を使用して製品を取得する必要があります。

私はまだ has_many を使って、関連を producer.derived_products に凝縮していないので、それを機能させることについてコメントすることはできません。

于 2012-02-15T14:43:46.013 に答える
-2
class Note < ActiveRecord::Base

 belongs_to :note_obj, :polymorphic => true
 belongs_to :user


end


class Contact < ActiveRecord::Base

 belongs_to :contact_obj, :polymorphic => true
 belongs_to :phone_type 

end



class CarrierHq < ActiveRecord::Base


 has_many :contacts, :as => :contact_obj
 has_many :notes, :as => :note_obj


end
于 2010-07-09T12:15:23.087 に答える