为什么Rails orphan通过关联连接多态的记录?

rob*_*sco 5 ruby-on-rails polymorphic-associations ruby-on-rails-3

提案文档可以分为许多不同的部分类型(文本,费用,时间表)等

这里使用连接表上的多态关联建模.

class Proposal < ActiveRecord::Base
  has_many :proposal_sections
  has_many :fee_summaries, :through => :proposal_sections, :source => :section, :source_type => 'FeeSummary'
end

class ProposalSection < ActiveRecord::Base
  belongs_to :proposal
  belongs_to :section, :polymorphic => true
end

class FeeSummary < ActiveRecord::Base
  has_many :proposal_sections, :as => :section
  has_many :proposals, :through => :proposal_sections 
end
Run Code Online (Sandbox Code Playgroud)

虽然#create工作正常

summary = @proposal.fee_summaries.create
summary.proposal == @propsal # true
Run Code Online (Sandbox Code Playgroud)

#new不要

summary = @proposal.fee_summaries.new
summary.proposal -> nil
Run Code Online (Sandbox Code Playgroud)

它应该返回零吗?

在常规的has_many和belongs_to初始化但尚未存在的记录仍将返回其父关联(内置在内存中).

为什么这不起作用,是否是预期的行为?

Schema.rb

 create_table "fee_summaries", :force => true do |t|
    t.datetime "created_at", :null => false
    t.datetime "updated_at", :null => false
  end

  create_table "proposal_sections", :force => true do |t|
    t.integer  "section_id"
    t.string   "section_type"
    t.integer  "proposal_id"
    t.datetime "created_at",   :null => false
    t.datetime "updated_at",   :null => false
  end

  create_table "proposals", :force => true do |t|
    t.datetime "created_at", :null => false
    t.datetime "updated_at", :null => false
  end
Run Code Online (Sandbox Code Playgroud)

ruby 2.0 rails 3.2.14

Kom*_*owy 3

ActiveRecord 无法知道proposal.fee_summaries 是fee_summary.proposal 的反向关联。这是因为您可以定义自己的关联名称,对其进行附加约束等 - 自动导出哪些关联与哪些关联相反,即使不是不可能,也是非常困难的。inverse_of因此,即使对于最简单的情况,您也需要通过关联声明上的选项明确告知它。下面是一个简单的直接关联的示例:

class Proposal < ActiveRecord::Base
  has_many :proposal_sections, :inverse_of => :proposal
end

class ProposalSection < ActiveRecord::Base
  belongs_to :proposal, :inverse_of => :proposal_sections
end

2.0.0-p353 :001 > proposal = Proposal.new
 => #<Proposal id: nil, created_at: nil, updated_at: nil> 
2.0.0-p353 :002 > section = proposal.proposal_sections.new
 => #<ProposalSection id: nil, proposal_id: nil, created_at: nil, updated_at: nil> 
2.0.0-p353 :003 > section.proposal
 => #<Proposal id: nil, created_at: nil, updated_at: nil> 
Run Code Online (Sandbox Code Playgroud)

不幸的是,inverse_of不支持间接 ( through) 和多态关联。因此,就您的情况而言,没有简单的方法可以使其发挥作用。我看到的唯一解决方法是保留记录(使用create),这样 AR 就可以按键查询关系并返回正确的结果。

检查文档以获取更多示例和说明:http://apidock.com/rails/ActiveRecord/Associations/ClassMethods