I know this topic has been approached several times before in various ways, but I haven't been able to synthesize the other questions to meet this particular use case for Rails 3:
I am trying to construct a data model in which there are Attachments and Attachables. Any Attachment can be connected with an Attachable, and vice-versa. I would like this to ultimately be used as a combination acts_as plugin (acts_as_attachable and acts_as_attachment).
My current schema uses an Attacher model with two polymorphic belongs_to relationships to attempt to accomplish this.
The specific case outlined here involves an Attachable model (Good) and two Attachment models (Image and Movie).
Here is what I have so far:
attacher.rb
class Attacher < ActiveRecord::Base
belongs_to :attachment, :polymorphic => true
belongs_to :attachable, :polymorphic => true
end
good.rb
class Good < ActiveRecord::Base
has_many :attachment_relations, :as => :attachable, :class_name => 'Attacher'
has_many :attached_images, :through => :attachment_relations, :source => :attachment, :source_type => 'Image'
has_many :attached_movies, :through => :attachment_relations, :source => :attachme开发者_Go百科nt, :source_type => 'Movie'
end
image.rb
class Image < ActiveRecord::Base
has_many :attachable_relations, :as => :attachment, :class_name => 'Attacher'
end
movie.rb
class Movie < ActiveRecord::Base
has_many :attachable_relations, :as => :attachment, :class_name => 'Attacher'
end
This works insofar as I can do the following:
@g = Good.create!
@i = Image.create!
@m = Movie.create!
@g.attached_images << @i
@g.attached_images # [#<Image id: 1 ... >]
@g.attached_movies << @m
@g.attached_movies # [#<Movie id: 1 ... >]
@g.attachment_relations # [#<Attacher id: 1, attachable_id: 1, attachable_type: "Good", attachment_id: 1, attachment_type: "Image" ...>, #<Attacher id: 2, attachable_id: 1, attachable_type: "Good", attachment_id: 1, attachment_type: "Movie" ...>]
The thrust of my question is: can I use associations to construct the following method/return so I can still do things like @g.attachments.where( ... )
:
@g.attachments # [#<Image id: 1 ... >, #<Movie id: 1 ... >]
I have tried a bunch of things like this:
good.rb
class Good < ActiveRecord::Base
has_many :attachment_relations, :as => :attachable, :class_name => 'Attacher'
has_many :attachments, :through => :attachment_relations
end
But they tend to throw me this:
ActiveRecord::HasManyThroughAssociationPolymorphicError: Cannot have a has_many :through association 'Good#attachments' on the polymorphic object 'Attachment#attachment'
I think I basically need something that could act like source_type => :any
...
Also, this is my first question on StackOverflow, so please let me know if there is anything I can do to improve my question. Thanks in advance! :)
Unfortunately, I have come to the conclusion that there isn't an easy or standard way to do this. The clearest basic solution I have found is from Squeegy's answer to this question: Rails polymorphic many to many association, where he references his gist to a reasonably simple has_relations module.
I think this basically answers my question and serves a good jumping-off point for creating a more robust solution.
sadly this is really not possible with rails, you can try your luck with this extension: https://github.com/kronn/has_many_polymorphs/tree/
You should be ready to go just by adding this line to your Gemfile:
gem 'kronn-has_many_polymorphs'
and running this command inside your rails application folder:
bundle
精彩评论