Rails是多态的has_one构建

时间:2014-01-24 16:06:25

标签: ruby-on-rails ruby-on-rails-4 associations polymorphic-associations has-one-through

给定ContentBlock模型:

class ContentBlock < ActiveRecord::Base
  has_one :block_association
  has_one :image, through: :block_association, source: :content, source_type: "Image"
  has_one :snippet, through: :block_association, source: :content, source_type: "Snippet"

  accepts_nested_attributes_for :image, allow_destroy: true
  accepts_nested_attributes_for :snippet, allow_destroy: true
end

BlockAssociation模型:

class BlockAssociation < ActiveRecord::Base
  belongs_to :content_block
  belongs_to :content, polymorphic: true
end

代码段模型:

class Snippet < ActiveRecord::Base
  has_one :block_association, as: :content
  has_one :content_block, through: :block_association

  validates :body, presence: true
end

我需要这样做:

@content_block.build_snippet

但这给出了:

undefined method 'build_snippet' for #<ContentBlock:0x007ffb7edde330>

我如何达到预期的效果?

表格将是这样的:

<%= simple_form_for @content_block do |f| %>
  <%= f.simple_fields_for f.object.snippet || f.object.build_snippet do |sf| %>
    <%= sf.input :body %>
  <% end %>
<% end %>

(最初我假设content_block只是belong_to :content, polymorphic: true,但由于多种content类型,这似乎不合适。)

这与我正在做的很接近,但我无法理解它:http://xtargets.com/2012/04/04/solving-polymorphic-hasone-through-building-and-nested-forms/

1 个答案:

答案 0 :(得分:0)

class ContentBlock < ActiveRecord::Base      
  has_one :snippet, through: :block_association, source: :content, source_type: "Snippet"
end

这告诉rails,你想要ContentBlock的实例(让这个实例使content_block)通过BlockAssociation有一个名为“snippet”的假类型“内容”的Snippet实例。因此,ContentBlock实例应该能够响应content_block.content,这将返回片段和/或图像的集合(我在代码片段中省略了图像部分)。 content_block如何只能调用尚无人知道的片段内容。

您的BlockAssociation模型知道什么:

class BlockAssociation < ActiveRecord::Base
  belongs_to :content_block
  belongs_to :content, polymorphic: true
end

它知道它属于content_block并且知道(因为它将响应内容)一个或多个内容具有content_type('Snippet')和content_id(1或任何片段id),这些组合与片段的关系

现在你缺少的是Snippet部分:

class Snippet < ActiveRecord::Base
  has_one :block_association, :as => :snippet_content
  has_one :content_block, :through => :content_association # I'm actually not quite sure of this
end

告诉block_association如何调用此类内容,因为您希望图像内容和代码段内容不同。现在content_block.snippet_content应该返回代码段,snippet.block_content应该返回block_content。

我希望我没有弄乱任何东西,这些关系总是让我头晕目眩