Rails Developer
Rails Developer

Reputation: 412

STI with Ploymorphic association in rails

I have model named Slider

class Slider < ActiveRecord::Base

end

and HomeBannerSlider which has single table inheritance relation with slider

class HomeBannerSlider < Slider

    has_many :images, as: :imageable
    accepts_nested_attributes_for :images, reject_if: :all_blank, allow_destroy: true

end

and Image model as given

class Image < ActiveRecord::Base
   belongs_to :imageable, polymorphic: true
   has_attached_file :image
end

My problem is whenever I save HomeBannerSlider with following command

      @admin_home_banner_slider = HomeBannerSlider.new(admin_home_banner_slider_params)

     @admin_home_banner_slider.save

It saves the imageable_type in Image model as Slider

@admin_home_banner_slider.images
<Image:0x007f5e6ef7af20
  id: nil,
  imageable_id: nil,
  imageable_type: "Slider",
  title: "2",
  description: "2",
  link_button: nil,
  link_button_title: nil,
  owner: nil,
  publish: nil,
  priority: nil,
  created_at: nil,
  updated_at: nil,
  image_file_name: nil,
  image_content_type: nil,
  image_file_size: nil,
  image_updated_at: nil>]

but i want it to store imageable_type as HomeBannerSlider

Upvotes: 3

Views: 520

Answers (3)

Thomas Walpole
Thomas Walpole

Reputation: 49890

From the activerecord documentation - http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Polymorphic+Associations - "Using polymorphic associations in combination with single table inheritance (STI) is a little tricky. In order for the associations to work as expected, ensure that you store the base model for the STI models in the type column of the polymorphic association".

So rails specifically wants the base type stored there, it will still load the correct type if you access my_image.imageable since it uses the type from the Slider table when creating that object and ids are unique for the whole Slider table, not just in each type in the table.

That all being said, there is a gem that adds the behavior you want to rails - https://github.com/appfolio/store_base_sti_class

Upvotes: 2

Sasidaran
Sasidaran

Reputation: 454

You can override the imageable_type in your model as

def imageable_type=(imageType)
  super(imageType.classify.constantize.base_class.to_s)
end

Upvotes: 1

Yang
Yang

Reputation: 1923

Try to add this in your Image model:

before_validation :set_type

def set_type
  self.imageable_type = imageable.class.name
end

Upvotes: 1

Related Questions