I implemented an example of Reverse Polymorphism in Rails with the selected answer from this question: Reverse Polymorphic Associations
With this we are able to do the following:
t = Article.new
t.article_elements # []
p = Picture.new
t.article_elements.create(:element => p)
t.article_elements # [<ArticleElement id: 1, article_id: 1, element_id: 1, element_type: "Picture", created_at: "2011-09-26 18:26:45", updated_at: "2011-09-26 18:26:45">]
t.pictures # [#<Picture id: 1, created_at: "2011-09-26 18:26:45", updated_at: "2011-09-26 18:26:45">]
I'm wondering if it's possible to modify this such that if I do t.article_elements
that I can also see the attributes for the picture to. So for example, if I had an picture_name attribute for the variable p, how can I access that from t.article_elements ? So basically, I am trying to access the parent's attributes from the child object.
Note that t.article_elements
is a collection. I will use article_element
to refer to one member of the collection.
Per your example,
article_element.element.picture_name
will work.
However, you run into a problem with undefined methods by mismatched attributes. For example, a video would not have a picture_name
attribute. If all element types shared a common attribute, such as name
, it would be fine.
One way to avoid this problem is to check whether the element responds to a given attribute method. For example:
# models/article_element.rb
def element_try(method)
self.element.respond_to?(method) ? self.element.send(method) : ""
end
If our element is a video and we call:
article_element.element_try(:picture_name) # => ""
we will get a blank string instead of NoMethodError
.
This solution is a bit hacky, so use at your own risk. Personally, I'd use common attributes instead.
I had similar situation.
class User < ActiveRecord::Base
has_one :image, as: :imageable
end
class Person < ActiveRecord::Base
has_one :image, as: :imageable
end
class Image < ActiveRecord::Base
belongs_to :imageable, :polymorphic => true
end
When you wanna access parent of image, you can do Image.last.imageable
and that will give you either User or Person object. It works same with has_many relations.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.