简体   繁体   English

在Rails中保存动态字段

[英]Save dynamic fields in Rails

In my Rails app I Pages, Blocks, BlockContents, Fields, and FieldContents. 在我的Rails应用程序中,我是Pages,Blocks,BlockContents,Fields和FieldContents。

The associations are: 关联是:

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

Using this I am able to have dynamic fields for Page. 使用此功能,我可以拥有Page的动态字段。

However writing to the DB is currently done in the controller like so: 但是,当前在控制器中完成对DB的写入,如下所示:

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

While this does in work, it's quite dirty and it doesn't show my validations for my FieldContent in the view (the validations do work as they don't save the FieldContent if they are invalid, but it should prevent the whole page from saving and show it in the view). 尽管此方法确实有效,但它很脏,并且不会在视图中显示我对FieldContent的验证(验证有效,因为如果验证无效,它们将不保存FieldContent,但应防止整个页面被保存并在视图中显示)。

How can I make it so that I can show the validations for FieldContent? 我该如何做才能显示FieldContent的验证?


For those that want to see the view: 对于那些想要查看视图的人:

<% @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 %>

and the helper I use to get the content: 和我用来获取内容的助手:

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

Firstly what you need to do firstly in order to submit a form containing multiple models is to accept nested attributes. 首先,要提交包含多个模型的表单,首先需要接受嵌套属性。

In your page.rb file, put: 在您的page.rb文件中,输入:

class Page < ActiveRecord::Base
has_many :blocks
has_many :block_contents, :through => :blocks
accepts_nested_attributes_for :field_contents

Secondly in the view - You must specify which fields are for which model using 'fields_for' So inside the form_for @page, you should put: 其次,在视图中-您必须使用“ fields_for”指定哪些字段适用于哪种模型,因此,在form_for @page中,应放置:

 <%= f.fields_for :field_contents do |b| %>

Since :field_contents is the only object that will be updated along with @page. 由于:field_contents是唯一将与@page一起更新的对象。 So that the form element in it's entirety looks like this: 这样整个表单元素看起来像这样:

<% @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 %>

Since I've learnt you can already access @page.field_content, you don't have to touch anything in the controller as it updates the record automatically based on the existing relation. 由于我已经知道您已经可以访问@ page.field_content,因此您无需触摸控制器中的任何内容,因为它会基于现有关系自动更新记录。

So now that we have all models being submitted in a single request, you specified that you want error messages to show inside the view after validation has taken place. 因此,既然我们已经在单个请求中提交了所有模型,那么您指定要在验证之后在视图内显示错误消息。 And this is the easy part. 这是容易的部分。

From what I can see, you're currently validating the presence of :content . 据我所知,您当前正在验证:content的存在。

In your view: simply put a HTML tag or a rails content tag 在您看来:只需放置一个HTML标签或Rails内容标签

<p class= "error"><%= "Your error message"if @field_content.errors[:content].present? %></p>

Let me know if you have any further questions. 如果您还有其他问题,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM