加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 21:45:40 所属栏目:百科 来源:网络整理
导读:我比较新的Rails.我想向使用多态关联的模型添加一个关联,但只返回一个特定类型的模型,例如: class Note ActiveRecord::Base # The true polymorphic association belongs_to :subject,polymorphic: true # Same as subject but where subject_type is 'Volu
我比较新的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,但我猜这应该适用于以前的版本.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读