在我的Rails应用程序中I Pages,Blocks,BlockContents,Fields和FieldContents。
协会是:
class Page < ActiveRecord::Base
has_many :blocks
has_many :block_contents, :through => :blocks
end
class Block < ActiveRecord::Base
belongs_to :page
has_many :block_contents
end
class BlockContent < ActiveRecord::Base
belongs_to :block
has_many :field_contents
end
class Field < ActiveRecord::Base
has_many :field_contents
end
class FieldContent < ActiveRecord::Base
belongs_to :block_content
belongs_to :field
validates :content, presence: true
end
使用此功能,我可以拥有Page。
的动态字段然而,写入数据库目前在控制器中完成,如下所示:
def update
@page = Page.find(params[:id])
if params[:field_content].present?
params[:field_content].each do |block_content|
block_content.last.each do |field|
field_content_row = FieldContent.where(block_content_id: block_content.first, field_id: field.first).first
if field_content_row.present?
field_content_row.update(content: field.last)
else
field_content = FieldContent.new
field_content.block_content_id = block_content.first
field_content.field_id = field.first
field_content.content = field.last
field_content.save
end
end
end
end
if @page.update_attributes(page_params)
redirect_to pages_path
else
render 'edit'
end
end
虽然这在工作中有效,但它很脏,并且它没有在视图中显示我对FieldContent的验证(验证确实有效,因为如果它们无效,它们不会保存FieldContent,但它应该可以防止整个保存页面并在视图中显示。)
如何制作它以便我可以显示FieldContent的验证?
对于那些想要查看视图的人:
<% @page.blocks.each do |block| %>
<% block.block_contents.each do |block_content| %>
<% field_group.fields.each do |field| %>
<input name="field_content[<%= block_content.id %>][<%= field.id %>]" id="field_content_<%= block_content.id %>_<%= field.id %>" type="text" value="<%= get_field_content(block_content, field.name) %>">
<% end %>
<% end %>
<% end %>
和我用来获取内容的助手:
def get_field_content(block_content, field)
content = ''
block_content.field_contents.each do |field_content|
if field_content.field.name == field && field_content.block_content_id == block_content.id
content = field_content.content
end
end
content
end
答案 0 :(得分:2)
首先,为了提交包含多个模型的表单,首先需要做的是接受嵌套属性。
在page.rb文件中,输入:
class Page < ActiveRecord::Base
has_many :blocks
has_many :block_contents, :through => :blocks
accepts_nested_attributes_for :field_contents
其次在视图中 - 您必须使用&#39; fields_for&#39;指定哪个模型适用于哪个模型。所以在form_for @page中,你应该把:
<%= f.fields_for :field_contents do |b| %>
因为:field_contents是唯一将与@page一起更新的对象。因此,它的整体形式元素如下所示:
<% @page.blocks.each do |block| %>
<% block.block_contents.each do |block_content| %>
<% field_group.fields.each do |field| %>
<%= form_for @page do |f| %>
<%= f.input :any attribute %>
<%= f.fields_for :field_contents do |b| %>
<%= b.text_field :content %>
<%= f.fields_for :block_contents do |b| %>
<%= b.hidden_field :block_content, value: "#{@block_content.id}"%>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
由于我已经了解到您已经可以访问@ page.field_content,因此您无需触摸控制器中的任何内容,因为它会根据现有关系自动更新记录。
现在我们已经在一个请求中提交了所有模型,您指定在验证发生后您希望在视图内显示错误消息。这是容易的部分。
从我所看到的情况来看,您目前正在验证:content
的存在。
在您的视图中:只需添加HTML标记或rails内容标记
<p class= "error"><%= "Your error message"if @field_content.errors[:content].present? %></p>
如果您有任何其他问题,请与我们联系。