Catfish Catfish - 5 months ago 28
Ruby Question

Rails dynamic form issue

I'm working on a dynamic form based off http://railscasts.com/episodes/197-nested-model-form-part-2.

I have this link:
views/shared/_new_field.html.erb

<%= link_to_add_fields "Add Field", f, :application_fields, @current_section.id %>


Which is here:
helpers/application_helper.rb

# Generates a link_to add a new application field.
def link_to_add_fields(name, f, association, section_id)
new_object = f.object.send(association).klass.new
id = new_object.object_id
fields = f.fields_for(association, new_object, child_index: id) do |builder|
render(association.to_s.singularize + "_fields", f: builder)
end
link_to(name, '#', class: "add_fields buttonS bBlue button", data: {id: id, fields: fields.gsub("\n", ""), section_id: section_id})
end


Which generates a form that when I fill out the fields and submit, it generates the params hash:

Parameters: {"utf8"=>"✓", "authenticity_token"=>"Cl8XQNZeKRMtpdE0MLNhEX3by67bEcntjaAxygsduyo=", "application"=>{"application_fields_attributes"=>{"1380071101589"=>{"field_name"=>"RRR", "field_type"=>"textfield", "required"=>"0", "_destroy"=>"false"}}}, "commit"=>"Create", "id"=>"1", "section_id"=>"2"}


And this is the controller method:

...
@application = current_company.applications.find(params[:id])
@application.update_attributes(params[:application])

if @application.update_attributes(params[:application])
...


The Problem

With my current controller method, it's not saving the
section_id
to the
ApplicationField
row.

I also tried this in my controller method:
...
@application = current_company.applications.find(params[:id])
@application.assign_attributes(params[:application])
@application.section_id = params[:section_id]

if @application.save
...


but that generates the error:

NoMethodError - undefined method `section_id=' for #<Application:0x007f8300138ca8>


I'm at a loss for what i need to do to get the section id to save to the ApplicationField row.

Models For Reference

class Application < ActiveRecord::Base
belongs_to :company
has_many :application_fields, :dependent => :destroy
accepts_nested_attributes_for :application_fields, :allow_destroy => true
attr_accessible :application_name, :company_id, :application_fields_attributes
end

class ApplicationField < ActiveRecord::Base
belongs_to :application
has_many :application_fields_values, :dependent => :destroy
attr_accessible :field_name, :field_type, :xposition, :yposition, :required, :application_id, :template_id, :options, :section_id
end


Output of field.inspect in helper method:

"<div class=\"application_field formRow add_fields_form\" id=\"new_application_field\" remote=\"true\">\n \n <div class=\"formRow\">\n\t <label for=\"application_application_fields_attributes_70100276854720_field_name\">Field name</label>\n\t <input id=\"application_application_fields_attributes_70100276854720_field_name\" name=\"application[application_fields_attributes][70100276854720][field_name]\" size=\"30\" type=\"text\" />\n\t</div>\n \n <div class=\"formRow\">\n\t <label for=\"application_application_fields_attributes_70100276854720_field_type\">Field type</label>\n\t <select class=\"select\" id=\"field_type_dropdown\" name=\"application[application_fields_attributes][70100276854720][field_type]\"><option value=\"textfield\">Textfield</option>\n<option value=\"checkbox\">Checkbox</option>\n<option value=\"dropdown\">Dropdown</option>\n<option value=\"biglabel\">Big Label</option>\n<option value=\"smalllabel\">Small Label</option></select>\n\t</div>\n \n <div class=\"formRow\">\n\t <input name=\"application[application_fields_attributes][70100276854720][required]\" type=\"hidden\" value=\"0\" /><input class=\"check\" id=\"application_application_fields_attributes_70100276854720_required\" name=\"application[application_fields_attributes][70100276854720][required]\" type=\"checkbox\" value=\"1\" />\n\t <label for=\"application_application_fields_attributes_70100276854720_required\">Required</label>\n\t</div>\n \n <!-- Need to store the hidden field _destroy here so we can access it via jQuery -->\n <input id=\"application_application_fields_attributes_70100276854720__destroy\" name=\"application[application_fields_attributes][70100276854720][_destroy]\" type=\"hidden\" value=\"false\" />\n \n <div class=\"grid1\" align=\"center\">\n \n </div>\n \n <div id=\"new_field_buttons\" class=\"formRow\">\n <div id=\"new_field_buttons\" class=\"fluid sideWidget\">\n <div class=\"grid6\">\n <input class=\"buttonS bBlue\" name=\"commit\" type=\"submit\" value=\"Create\" />\n </div>\n <div class=\"grid6\">\n <input id=\"cancel_new_field\" class=\"buttonS bRed\" type=\"button\" value=\"Cancel\">\n </div>\n </div>\n </div>\n <div class=\"clear\"></div>\n</div>\n"
ributes][70100276854720][_destroy]\" type=\"hidden\" value=\"false\" />\n \n <div class=\"grid1\" align=\"center\">\n \n </div>\n \n <div id=\"new_field_buttons\" class=\"formRow\">\n <div id=\"new_field_buttons\" class=\"fluid sideWidget\">\n <div class=\"grid6\">\n <input class=\"buttonS bBlue\" name=\"commit\" type=\"submit\" value=\"Create\" />\n </div>\n <div class=\"grid6\">\n <input id=\"cancel_new_field\" class=\"buttonS bRed\" type=\"button\" value=\"Cancel\">\n </div>\n </div>\n </div>\n <div class=\"clear\"></div>\n</div>\n"
<input class=\"buttonS bBlue\" name=\"commit\" type=\"submit\" value=\"Create\" />\n </div>\n <div class=\"grid6\">\n <input id=\"cancel_new_field\" class=\"buttonS bRed\" type=\"button\" value=\"Cancel\">\n </div>\n </div>\n </div>\n <div class=\"clear\"></div>\n</div>\n"
div class=\"clear\"></div>\n</div>\n"

Answer

Instead of passing the section_id to the link_to method, try passing it as a variable to the render method like so:

render(association.to_s.singularize + "_fields", f: builder, section_id: section_id)

This way you can just insert a hidden field in your application_field_fields partial that adds the section_id to the form data that is posted to your controller:

<%= f.hidden_field :section_id, :value => section_id %>