Reputation: 1491
I have a polymorphic association on an Image
model and need to have two associations on it from a Place
model. Something like:
class Place < ActiveRecord::Base
has_many :pictures, as: :imageable, class_name: 'Image'
has_one :cover_image, as: :imageable, class_name: 'Image'
end
class Image < ActiveRecord::Base
belongs_to :imageable, polymorphic: true
end
This obviously doesn't work has the Image
model doesn't know the difference between pictures and cover_image and every image is stored with
#<Image ... imageable_id: 17, imageable_type: "Place">
I was thinking about adding a imageable_sub_type
column to Image
to store a subtype.. So my images would look like:
#<Image ... imageable_id: 17, imageable_type: "Place", imageable_sub_type: "cover_image">
I can easily retrieve only the images with that subtype from my association in Place
:
has_one :cover_image, -> { where(imageable_sub_type: 'cover_image'), as: :imageable, class_name: 'Image'
But I don't find a way to set this value while adding an image to a Place
(actually it is always set to nil
).
Is there a way to do that?
I tried to do it this way: https://stackoverflow.com/a/3078286/1015177 but the problem remains the same, the imageable_sub_type
remains nil
.
Upvotes: 2
Views: 2317
Reputation: 8003
by adding the condition in the relation, it is letting you retrieve the images
with imageable_sub_type = cover_image
when you call place.cover_image
. It will not set the attribute for you when you add the image. That has to be done separately when the image is added based on some input from the view like a checkbox tag.
Update: You can override the default association=
method , sthing like below in Place
model:
def cover_image=(img)
# add the img to tthe associated pictures
self.pictures << img
# mark current img type as cover
img.update_attribute(:imageable_sub_type, "cover_image")
# mark all other images type as nil, this to avoid multiple cover images,
Picture.update_all( {:imageable_sub_type => nil}, {:id => (self.pictures-[img])} )
end
Upvotes: 0
Reputation: 11
When using a condition on a relation, it will assign that condition if you build the record through the relation (ie using create_cover_image).
If you want it to change the value of imageable_sub_type when assigning an exiting instance of Image, then you could overwrite cover_image= to do that. ie
def cover_image= cover_image
cover_image.imageable_sub_type = 'cover_image'
super
end
Upvotes: 1