简体   繁体   中英

Reverse Polymorphic Association in Rails (Accessing the parent's attributes)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM