ruby-on-rails – 特定类型的多态属性的关联

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 特定类型的多态属性的关联前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我比较新的Rails.我想向使用多态关联的模型添加一个关联,但只返回一个特定类型的模型,例如:
class Note < ActiveRecord::Base
  # The true polymorphic association
  belongs_to :subject,polymorphic: true

  # Same as subject but where subject_type is 'Volunteer'
  belongs_to :volunteer,source_association: :subject
  # Same as subject but where subject_type is 'Participation'
  belongs_to :participation,source_association: :subject
end

我已经尝试了大量的组合,从阅读关于ApiDock的关联,但没有什么似乎完全正是我想要的.这是我迄今为止最好的

class Note < ActiveRecord::Base
  belongs_to :subject,polymorphic: true
  belongs_to :volunteer,class_name: "Volunteer",foreign_key: :subject_id,conditions: {notes: {subject_type: "Volunteer"}}
  belongs_to :participation,class_name: "Participation",conditions: {notes: {subject_type: "Participation"}}
end

我想通过这个测试:

describe Note do
  context 'on volunteer' do
    let!(:volunteer) { create(:volunteer) }
    let!(:note) { create(:note,subject: volunteer) }
    let!(:unrelated_note) { create(:note) }

    it 'narrows note scope to volunteer' do
      scoped = Note.scoped
      scoped = scoped.joins(:volunteer).where(volunteers: {id: volunteer.id})
      expect(scoped.count).to be 1
      expect(scoped.first.id).to eq note.id
    end

    it 'allows access to the volunteer' do
      expect(note.volunteer).to eq volunteer
    end

    it 'does not return participation' do
      expect(note.participation).to be_nil
    end

  end
end

第一个测试通过,但您不能直接调用该关系:

1) Note on volunteer allows access to the volunteer
     Failure/Error: expect(note.reload.volunteer).to eq volunteer
     ActiveRecord::StatementInvalid:
       PG::Error: ERROR:  missing FROM-clause entry for table "notes"
       LINE 1: ...."deleted" = 'f' AND "volunteers"."id" = 7798 AND "notes"."s...
                                                                    ^
       : SELECT  "volunteers".* FROM "volunteers"  WHERE "volunteers"."deleted" = 'f' AND "volunteers"."id" = 7798 AND "notes"."subject_type" = 'Volunteer' LIMIT 1
     # ./spec/models/note_spec.rb:10:in `block (3 levels) in <top (required)>'

为什么?

我想这样做的原因是因为我正在构建基于解析查询字符串的范围,包括连接到各种模型/ etc;用于构造范围的代码比以上复杂得多 – 它使用collection.reflections等.我目前的解决方案适用于此,但是冒犯了我,我不能直接从注释的实例调用关系.

我可以通过将其分为两个问题来解决这个问题:直接使用范围

scope :scoped_by_volunteer_id,lambda { |volunteer_id| where({subject_type: 'Volunteer',subject_id: volunteer_id}) }
  scope :scoped_by_participation_id,lambda { |participation_id| where({subject_type: 'Participation',subject_id: participation_id}) }

然后只是使用一个吸引器的note.volunteer / note.participation,只是返回note.subject如果它有正确的subject_type(否则为nil),但我认为在Rails必须有一个更好的方法

解决方法

我碰到了类似的问题.我终于通过使用如下所示的自我参考协会来解决了最好和最强大的解决方案.
class Note < ActiveRecord::Base
  # The true polymorphic association
  belongs_to :subject,polymorphic: true

  # The trick to solve this problem
  has_one :self_ref,:class_name => self,:foreign_key => :id

  has_one :volunteer,:through => :self_ref,:source => :subject,:source_type => Volunteer
  has_one :participation,:source_type => Participation
end

清洁&简单,只测试了Rails 4.1,但我猜这应该适用于以前的版本.

原文链接:https://www.f2er.com/ruby/266930.html

猜你在找的Ruby相关文章