Czy to poprawne zastosowanie relacji polimorficznej

chciałbym się upewnić czy w tym przypadku zastosowanie relacji polimorficznej ma sens. Modele wyglądają tak:

[code]class Order < ActiveRecord::Base
belongs_to :orderable, :polymorphic => true
belongs_to :user
end

class Recruitment < ActiveRecord::Base
has_one :order, :as => :orderable
has_one :user, :through => :orders
end

class Link < ActiveRecord::Base
has_one :order, :as => :orderable
has_one :user, :through => :orders
end[/code]
Część wspólna wszystkich Orders jest zgrupowana w modelu Order a konkretne rodzaje zamówień w klasach np. Recruitment, Link i pare innych. Czy polymorphic to dobry pomysł w tym przypadku. Dotychczas spotykałem się tylko z przykładami jak ten z Rails Guides. Jeśli bedę pobierał elementy to będe jechał po Orders, czy można jakoś elegancko pobrać zmienne z konkretnego typu i przypisać je do @order czy poprostu switch na orderable_type ?

[code]class Picture < ActiveRecord::Base
belongs_to :imageable, :polymorphic => true
end

class Employee < ActiveRecord::Base
has_many :pictures, :as => :imageable
end

class Product < ActiveRecord::Base
has_many :pictures, :as => :imageable
end[/code]

Hmm a może konkretne rodzaje zamówień powinny być potomkami klasy Order? Polimorficzne powiązania powinny IMHO dotyczyć całkowicie odmiennego modelu, który ma powiązania z kilkoma innymi. U ciebie modele są “spokrewnione”. Ale niech się mądrzejsi wypowiedzą.

czyli wtedy Order miało by poprostu has_one: link, recruitment… (tyle że jeden order ma zawsze tylko jeden z tych rodzaji)
możliwe że masz rację, sam mam wątpliwości, poczeka się na innych co poradzą :slight_smile:

Ja myślę, że Tubis dobrze radzi… tzn dopiero po jego odpowiedzi zrozumiałem o co w tych modelach może chodzić :wink: chyba coś takiego:

[code=ruby]class Order < ActiveRecord::Base
belongs_to :user
end

class Recruitment < Order
end

class Link < Order
end[/code]
…tylko nie wiem czy u Ciebie można uznać że Recruitment jest Orderem. Nie brzmi to naturalnie, ale struktura robi się o wiele prostsza.

Poczytaj o Single-table Inheritance tutaj: http://api.rubyonrails.org/classes/ActiveRecord/Base.html
Pamiętaj o kolumnie “type” w tabeli orders jeśli pójdziesz w tą stronę.

Dzięki.
Tak, recruitment jest pewnym typem zlecenia, zlecenie nazwałem Order ponieważ nie mogłem znaleźć lepszego angielskiego odpowiednika,a request kojarzy się bardziej z żądaniem do servera, przynajmniej dla mnie :).
Jeśli zdefinuje takie zależności to jak można elegancko dodać nowy wpis np. nowy Link żeby uzupełniło dane zarówno w tabeli links jak i orders, tak jakbym dodawał normalnie do modelu bez rodzica ?
Domyslam się że w takim przypadku nazwy pół w rodzicu i dziecku nie mogą sie powtarzać ?
Czy wtedy od strony Order bedę mógł się dobrać do np. przypisanego Link, może trzeba dodać order_id w links ?

spóbowałem ale coś nie działa, Jeśli tworze nowy objekt np. Recruitments.new() i ustawie któryś z parametrów z tabeli recruitments to dostaję

>> r = Recruitment.new(:type_other => "test") ActiveRecord::UnknownAttributeError: unknown attribute: type_other from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2744:in `attributes=' from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2740:in `each' from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2740:in `attributes=' from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2438:in `initialize' from (irb):1:in `new' from (irb):1 from :0
Jeśli natomiast parametr jest z Orders to zapisuje się poprawnie ale tylko w tabeli orders. Powinno chyba zapisywać dane w obu tabelach ?

z tego co znalazłem w przykładzie z Agile Web Development with Rails, parametry dla każdego typu są zdefiniowane w głównej tabeli, w tym momencie będzie sporo pustych wartości.

[code]create_table :people, :force => true do |t|
t.string :type

common attributes

t.string :name
t.string :email

attributes for type=Customer

t.decimal :balance, :precision => 10, :scale => 2

attributes for type=Employee

t.integer :reports_to
t.integer :dept

attributes for type=Manager

– none –

end

class Person < ActiveRecord::Base
end
class Customer < Person
end

class Employee < Person
belongs_to :boss, :class_name => “Manager” , :foreign_key => :reports_to
end

class Manager < Employee
end[/code]
Czy tak zawsze musi być, nie można mieć ich w dwóch tabelach, parent i child ?