On Tue, Feb 9, 2010 at 05:40, tsenart <tsen...@gmail.com> wrote: > ActiveRecord supports one-to-many polymorphic associations but not > many-to-many polymorphic associations. Thats what I wanted. > I emulate that behavior like this: > We have three models: - Article, Asset and Relationship > > class Article < PolyRecord > habtm_polymorphs [:assets] > end > > class Asset < PolyRecord > habtm_polymorphs [:articles] > end > > class Relationship < ActiveRecord::Base > belongs_to :origin, :polymorphic => true > belongs_to :destination, :polymorphic => true > > after_create :create_reverse_relationship > > private > def create_reverse_relationship > rev = Relationship.new :origin => self.destination, :destination > => self.origin > rev.save(false) > true > end > > end > > class PolyRecord < ActiveRecord::Base > self.abstract_class = true > > def self.habtm_polymorphs(associations, options={}) > associations = [associations].flatten > options[:polymorphic_join_table] ||= 'relationships' > options[:polymorphic_from] ||= 'origin' > options[:polymorphic_to] ||= 'destination' > > pjoin = options[:polymorphic_join_table] > pto = options[:polymorphic_to] > pfrom = options[:polymorphic_from] > > has_many pjoin, :as => pto > has_many pjoin, :as => pfrom > > associations.each do |assoc| > has_many assoc, :through => pjoin, :source => pto, :source_type > => assoc.to_s.singularize.camelize > end > > after_destroy do |obj| > Relationship.delete_all({ > :destination_id => obj.id, > :destination_type => obj.class.to_s > }) > > Relationship.delete_all({ > :origin_id => obj.id, > :origin_type => obj.class.to_s > }) > end > > associations.each do |assoc| > define_method "#{assoc}=".to_sym do |args| > eval "self.#{assoc}.clear" > args = [args].flatten > > Relationship.delete_all({ > :origin_type => assoc.to_s.singularize.capitalize, > :destination_id => self.id, > :destination_type => self.class.to_s }) > > Relationship.destroy_all({ > :origin_id => self.id, > :origin_type => self.class.to_s, > :destination_type => assoc.to_s.singularize.camelize }) > > eval "self.#{assoc} << args" unless args.empty? > end > end > > end > end > > > Then you can use it like this: > @asset = Asset.new > @asset.articles = Article.first > @asset.articles = Article.all > @asset.articles << Article.new > @article.assets = �...@asset.articles.first.assets.last > > > On Feb 8, 11:18 pm, tsenart <tsen...@gmail.com> wrote: >> Very cool! Thanks for the answer. But inverse associations are only a >> component of those double sided polymorphic associations. >> At the present you can only make one sided associations. Table talking >> it means the following: >> >> Single sided polymorphic: >> ----------------------------------------------- >> | origin_id | destination_id | destination_type | >> ----------------------------------------------- >> >> Double sided polymorphic: >> ------------------------------------------------------------- >> | origin_id | origin_type | destination_id | destination_type | >> ------------------------------------------------------------- >> >> This way there's only on table to track all these relations. It allows >> every model to be associated with every other model as many times as >> needed. >> For a better explanation I wrote something on Stackoverflow -> Here is >> the link >> again:http://stackoverflow.com/questions/2224994/why-are-double-sided-polym... >> >> On Feb 8, 10:12 pm, Mat Brown <m...@patch.com> wrote: >> >> >> >> > Inverse associations will be standard in Rails 2.3.6. For the >> > impatient, here's a backport: >> >> >http://github.com/oggy/inverse_of >> >> > Mat >> >> > On Mon, Feb 8, 2010 at 16:43, tsenart <tsen...@gmail.com> wrote: >> > >http://stackoverflow.com/questions/2224994/why-are-double-sided-polym... >> >> > > -- >> > > You received this message because you are subscribed to the Google >> > > Groups "Ruby on Rails: Talk" group. >> > > To post to this group, send email to rubyonrails-t...@googlegroups.com. >> > > To unsubscribe from this group, send email to >> > > rubyonrails-talk+unsubscr...@googlegroups.com. >> > > For more options, visit this group >> > > athttp://groups.google.com/group/rubyonrails-talk?hl=en. > > -- > You received this message because you are subscribed to the Google Groups > "Ruby on Rails: Talk" group. > To post to this group, send email to rubyonrails-t...@googlegroups.com. > To unsubscribe from this group, send email to > rubyonrails-talk+unsubscr...@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/rubyonrails-talk?hl=en. > >
Ah, I see what you're getting at. When I've had to do that, I use full-blown model for the join table, and then a has_many :through to define the relationship between the endpoints. It's not a perfect solution but probably the best that's possible in AR. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-t...@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-talk+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.