在Rails中保存动态字段

时间:2017-01-05 15:34:38

标签: ruby-on-rails

在我的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

1 个答案:

答案 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>

如果您有任何其他问题,请与我们联系。