Rails Polymorphic Association with multiple associations on the same model

后端 未结 10 1858
无人及你
无人及你 2020-11-28 03:01

My question is essentially the same as this one: Polymorphic Association with multiple associations on the same model

However, the proposed/accepted solution does no

相关标签:
10条回答
  • 2020-11-28 03:57

    None of these solutions seem to work on Rails 5. For some reason, it looks like the behaviour around the association conditions has changed. When assigning the related object, the conditions don't seem to be used in the insert; only when reading the association.

    My solution was to override the setter method for the association:

    has_one :photo, -> { photo_type: 'primary_photo'},
            as: 'attachable',
            dependent: :destroy
    
    def photo=(photo)
      photo.photo_type = 'primary_photo'
      super
    end
    
    0 讨论(0)
  • 2020-11-28 03:58

    None of the previous answers helped me solve this problem, so I'll put this here incase anyone else runs into this. Using Rails 4.2 +.

    Create the migration (assuming you have an Addresses table already):

    class AddPolymorphicColumnsToAddress < ActiveRecord::Migration
      def change
        add_column :addresses, :addressable_type, :string, index: true
        add_column :addresses, :addressable_id, :integer, index: true
        add_column :addresses, :addressable_scope, :string, index: true
      end
    end
    

    Setup your polymorphic association:

    class Address < ActiveRecord::Base
      belongs_to :addressable, polymorphic: true
    end
    

    Setup the class where the association will be called from:

    class Order < ActiveRecord::Base
      has_one :bill_address, -> { where(addressable_scope: :bill_address) }, as: :addressable,  class_name: "Address", dependent: :destroy
      accepts_nested_attributes_for :bill_address, allow_destroy: true
    
      has_one :ship_address, -> { where(addressable_scope: :ship_address) }, as: :addressable, class_name: "Address", dependent: :destroy
      accepts_nested_attributes_for :ship_address, allow_destroy: true
    end
    

    The trick is that you have to call the build method on the Order instance or the scope column won't be populated.

    So this does NOT work:

    address = {attr1: "value"... etc...}
    order = Order.new(bill_address: address)
    order.save!
    

    However, this DOES WORK.

    address = {attr1: "value"... etc...}
    order = Order.new
    order.build_bill_address(address)
    order.save!
    

    Hope that helps someone else.

    0 讨论(0)
  • 2020-11-28 03:58

    Can you add a SecondaryPhoto model like:

    class SecondaryPhoto < Photo
    end
    

    and then skip the :class_name from the has_one :secondary_photo?

    0 讨论(0)
  • 2020-11-28 03:59

    In Rails 5 you have to define attr_accessor for :attachable_id and specify for relation :class_name and :foreign_key options only. You will get ...AND attachable_type = 'SecondaryPhoto' if as: :attachable used

    class Post
      attr_accessor :attachable_id
      has_one :photo, :as => :attachable, :dependent => :destroy
      has_one :secondary_photo, -> { where attachable_type: 'SecondaryPhoto' }, class_name: "Photo", dependent: :destroy, foreign_key: :attachable_id
    

    Rails 4.2+

    class Photo
       belongs_to :attachable, :polymorphic => true
    end
    
    class Post
       has_one :photo, :as => :attachable, :dependent => :destroy
       has_one :secondary_photo, -> { where attachable_type: "SecondaryPhoto"},
         class_name: Photo, foreign_key: :attachable_id,
         foreign_type: :attachable_type, dependent: :destroy
    end
    

    You need to provide foreign_key according ....able'ness or Rails will ask for post_id column in photo table. Attachable_type column will fills with Rails magic as SecondaryPhoto

    0 讨论(0)
提交回复
热议问题