Saving Dynamic Fields in Rails

In the Rails app, I have Pages, Blocks, BlockContents, Fields, and FieldContents.

Associations:

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 can have dynamic fields for the page.

However, writing to the database is currently performed in the controller as follows:

 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 works, it is rather dirty and it does not show my checks for my field in the view (checks are performed because they do not save the field element if they are invalid, but this should prevent the whole from saving and show it in the view).

How can I do this to show confirmations for FieldContent?


For those who want to see the performance:

 <% @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 that 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 
+6
source share
1 answer

First, what you need to do first, to submit a form containing multiple models, is to accept nested attributes.

In the page.rb file, put:

 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 indicate which fields for this model are used using the fields 'fields_for' So inside form_for @page, you must put:

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

Since: field_contents is the only object that will be updated with @page. So the form element in it 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 learned that you can already access @ page.field_content, you do not need to touch anything in the controller, as it automatically updates the record based on the existing relationship.

So, now that all the models are presented in one request, you indicated that error messages should be displayed inside the view after the check has been performed. And this is the easy part.

From what I see, you are currently checking for :content .

In your opinion: just put the HTML tag or the rails content tag

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

Let me know if you have further questions.

+2
source

Source: https://habr.com/ru/post/1013799/


All Articles