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.

Reply via email to