동일한 모델에서 여러 연결이있는 Rails Polymorphic Association
내 질문은 본질적으로 다음과 동일 합니다. 동일한 모델에 여러 연결이있는 다형성 연결
그러나 제안 / 수락 된 솔루션은 나중에 설명자가 설명하는 것처럼 작동하지 않습니다.
내 앱 전체에서 사용되는 Photo 클래스가 있습니다. 게시물에는 하나의 사진이있을 수 있습니다. 그러나 보조 사진을 추가하기 위해 다형성 관계를 다시 사용하고 싶습니다.
전에:
class Photo
belongs_to :attachable, :polymorphic => true
end
class Post
has_one :photo, :as => :attachable, :dependent => :destroy
end
원하는 :
class Photo
belongs_to :attachable, :polymorphic => true
end
class Post
has_one :photo, :as => :attachable, :dependent => :destroy
has_one :secondary_photo, :as => :attachable, :dependent => :destroy
end
그러나 "SecondaryPhoto"클래스를 찾을 수 없으므로 실패합니다. 다른 스레드에서 말할 수있는 내용을 바탕으로 다음과 같이하고 싶습니다.
has_one :secondary_photo, :as => :attachable, :class_name => "Photo", :dependent => :destroy
Post # secondary_photo를 호출하는 것을 제외하고는 단순히 사진 연결을 통해 첨부 된 동일한 사진을 반환합니다 (예 : Post # photo === Post # secondary_photo). SQL을 보면 내가 원하는대로 "SecondaryPhoto"대신 WHERE type = "Photo"를 수행합니다.
생각? 감사!
내 프로젝트에서 그렇게했습니다.
트릭은 사진에 기본 사진과 보조 사진을 구분하기 위해 has_one 조건에서 사용할 열이 필요하다는 것입니다. :conditions
여기서 무슨 일이 일어나는지 주목 하세요.
has_one :photo, :as => 'attachable',
:conditions => {:photo_type => 'primary_photo'}, :dependent => :destroy
has_one :secondary_photo, :class_name => 'Photo', :as => 'attachable',
:conditions => {:photo_type => 'secondary_photo'}, :dependent => :destroy
이 접근 방식 @post.build_photo
의 장점은를 사용하여 사진을 만들 때 photo_type이 'primary_photo'와 같은 해당 유형으로 자동으로 미리 채워진다는 것입니다. ActiveRecord는 그렇게 할만큼 똑똑합니다.
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
.... able'ness에 따라 foreign_key를 제공해야합니다. 그렇지 않으면 Rails가 사진 테이블에 post_id 열을 요청합니다. Attachable_type 열은 Rails 매직으로 채워집니다.SecondaryPhoto
이 게시물을 확인하는 사람들을위한 향후 참조
이것은 다음 코드를 사용하여 달성 할 수 있습니다.
레일즈 3 :
has_one :banner_image, conditions: { attachable_type: 'ThemeBannerAttachment' }, class_name: 'Attachment', foreign_key: 'attachable_id', dependent: :destroy
레일스 4 :
has_one :banner_image, -> { where attachable_type: 'ThemeBannerAttachment'}, class_name: 'Attachment', dependent: :destroy
이유는 확실하지 않지만 Rails 3에서는 조건 및 class_name과 함께 foreign_key 값을 제공해야합니다. 다형성 유형을 설정할 때 자동으로 호출 클래스 이름을 사용하므로 'as : : attachable'을 사용하지 마십시오.
위의 내용은 has_many에도 적용됩니다.
다음과 같은 것이 쿼리에 작동했지만 사용자에서 주소로 할당이 작동하지 않았습니다.
사용자 클래스
has_many :addresses, as: :address_holder
has_many :delivery_addresses, -> { where :address_holder_type => "UserDelivery" },
class_name: "Address", foreign_key: "address_holder_id"
주소 등급
belongs_to :address_holder, polymorphic: true
이전 답변 중 어느 것도이 문제를 해결하는 데 도움이되지 않았으므로 다른 사람이이 문제에 부딪 힐 경우를 대비하여 여기에 넣겠습니다. Rails 4.2 이상 사용.
마이그레이션을 생성합니다 (이미 Addresses 테이블이 있다고 가정).
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
다형성 연관을 설정하십시오.
class Address < ActiveRecord::Base
belongs_to :addressable, polymorphic: true
end
연결이 호출 될 클래스를 설정합니다.
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
트릭은 Order
인스턴스 에서 빌드 메서드를 호출해야한다는 scope
것입니다. 그렇지 않으면 열이 채워지지 않습니다.
따라서 이것은 작동하지 않습니다.
address = {attr1: "value"... etc...}
order = Order.new(bill_address: address)
order.save!
그러나 이것은 작동합니다.
address = {attr1: "value"... etc...}
order = Order.new
order.build_bill_address(address)
order.save!
다른 사람에게 도움이되기를 바랍니다.
나는 그것을 사용하지 않았지만 주변을 검색하고 Rails 소스를 살펴 보았고 찾고있는 것이 :foreign_type
. 그것을 시도하고 그것이 작동하는지 말하십시오 :)
has_one :secondary_photo, :as => :attachable, :class_name => "Photo", :dependent => :destroy, :foreign_type => 'SecondaryPost'
질문의 유형은 각각 및 Post
대신 모델에 할당 된대로 Photo
사용 SecondaryPost
하는 것이 좋습니다 Post
.
편집하다:
위의 답변은 완전히 잘못되었습니다. 연관된 모델의 유형을 포함하는 열의 이름을 지정하기 위해 연관 :foreign_type
되는 다형성 모델에서 사용할 belongs_to
수 있습니다.
Rails 소스를 살펴보면이 줄은 연결을 위해이 유형을 설정합니다.
dependent_conditions << "#{reflection.options[:as]}_type = '#{base_class.name}'" if reflection.options[:as]
보시다시피 base_class.name
유형 이름을 얻는 데 사용 됩니다. 내가 아는 한 당신은 그것으로 아무것도 할 수 없습니다.
그래서 내 제안은 사진 모델에 하나의 열을 추가하는 것 photo_type
입니다. 첫 번째 사진이면 0으로, 두 번째 사진이면 1로 설정합니다. 연결 에서 각각 :conditions => {:photo_type => 0}
및을 추가하십시오 :conditions => {:photo_type => 1}
. 당신이 찾고있는 해결책이 아니라는 것을 알고 있지만 더 나은 것을 찾을 수 없습니다. 그건 그렇고, 그냥 has_many
연관을 사용하는 것이 더 나을까요?
Your going to have to monkey patch the notion of foreign_type into has_one relationship. This is what i did for has_many. In a new .rb file in your initializers folder i called mine add_foreign_type_support.rb It lets you specify what your attachable_type is to be. Example: has_many photo, :class_name => "Picture", :as => attachable, :foreign_type => 'Pic'
module ActiveRecord
module Associations
class HasManyAssociation < AssociationCollection #:nodoc:
protected
def construct_sql
case
when @reflection.options[:finder_sql]
@finder_sql = interpolate_sql(@reflection.options[:finder_sql])
when @reflection.options[:as]
resource_type = @reflection.options[:foreign_type].to_s.camelize || @owner.class.base_class.name.to_s
@finder_sql = "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_id = #{owner_quoted_id} AND "
@finder_sql += "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote_value(resource_type)}"
else
@finder_sql += ")"
end
@finder_sql << " AND (#{conditions})" if conditions
else
@finder_sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} = #{owner_quoted_id}"
@finder_sql << " AND (#{conditions})" if conditions
end
if @reflection.options[:counter_sql]
@counter_sql = interpolate_sql(@reflection.options[:counter_sql])
elsif @reflection.options[:finder_sql]
# replace the SELECT clause with COUNT(*), preserving any hints within /* ... */
@reflection.options[:counter_sql] = @reflection.options[:finder_sql].sub(/SELECT (\/\*.*?\*\/ )?(.*)\bFROM\b/im) { "SELECT #{$1}COUNT(*) FROM" }
@counter_sql = interpolate_sql(@reflection.options[:counter_sql])
else
@counter_sql = @finder_sql
end
end
end
end
end
# Add foreign_type to options list
module ActiveRecord
module Associations # :nodoc:
module ClassMethods
private
mattr_accessor :valid_keys_for_has_many_association
@@valid_keys_for_has_many_association = [
:class_name, :table_name, :foreign_key, :primary_key,
:dependent,
:select, :conditions, :include, :order, :group, :having, :limit, :offset,
:as, :foreign_type, :through, :source, :source_type,
:uniq,
:finder_sql, :counter_sql,
:before_add, :after_add, :before_remove, :after_remove,
:extend, :readonly,
:validate, :inverse_of
]
end
end
For mongoid use this solution
Had tough times after discovering this issue but got cool solution that works
Add to your Gemfile
gem 'mongoid-multiple-polymorphic'
And this works like a charm:
class Resource
has_one :icon, as: :assetable, class_name: 'Asset', dependent: :destroy, autosave: true
has_one :preview, as: :assetable, class_name: 'Asset', dependent: :destroy, autosave: true
end
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
Can you add a SecondaryPhoto model like:
class SecondaryPhoto < Photo
end
and then skip the :class_name from the has_one :secondary_photo?
ReferenceURL : https://stackoverflow.com/questions/2494452/rails-polymorphic-association-with-multiple-associations-on-the-same-model
'programing' 카테고리의 다른 글
tensorflow에서 일부 변수 / 범위를 "고정": stop_gradient 대 변수 전달을 최소화 (0) | 2021.01.18 |
---|---|
PHP는 null이 0이라고 간주합니다. (0) | 2021.01.18 |
두 개의 IEnumerable을 동시에 반복하는 방법은 무엇입니까? (0) | 2021.01.18 |
Javascript에서 ISO 8601 날짜 구문 분석 (0) | 2021.01.18 |
번 들러가 Rubygems 1.5.0으로 업그레이드 한 후 초기화되지 않은 상수 Gem :: SilentUI (NameError) 오류를 발생시킵니다. (0) | 2021.01.18 |