2

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.

Community
  • 1
  • 1
TimPetricola
  • 1,491
  • 2
  • 12
  • 24
  • Have you tried with the syntax provided in the post you linked? i.e. `conditions: { imageable_sub_type: 'cover_image' }` instead of using a `lambda` with a `where`? – Raindal Sep 20 '13 at 15:08
  • Yes but `conditions` is deprecated. But the result was the same anyway. – TimPetricola Sep 20 '13 at 15:10
  • @TimPetricola updated the answer with a possible solution – tihom Sep 24 '13 at 02:41
  • possible duplicate of [Rails Polymorphic Association with multiple associations on the same model](http://stackoverflow.com/questions/2494452/rails-polymorphic-association-with-multiple-associations-on-the-same-model) – Joshua Pinter May 28 '15 at 17:38

2 Answers2

1

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
Lachlan
  • 11
  • 1
  • Thanks for that! Looks good, but I think I will keep the control in my controller for more flexibility (and not having to define methods for every relation with Image in every model) – TimPetricola Sep 27 '13 at 09:08
0

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
tihom
  • 7,923
  • 1
  • 25
  • 29
  • I was trying to automate it but seems that there is now way to do it. So thanks for your answer, I'm gonna do it like that! – TimPetricola Sep 21 '13 at 22:10