rails how to pass nested parameters - ruby-on-rails

I have a strong parameter like this
params.require(:survey).permit( option_booleans_attributes: [:id, :survey_id, :topic, :answer])
if I use rails f.input I got parameter like
"option_booleans_attributes"=>{"0"=>{"answer"=>"true", "id"=>"5"}, "1"=>{"answer"=>"false", "id"=>"6"}, "2"=>{"answer"=>"true", "id"=>"7"}}}
but I need to show option_booleans topic and let user fill answer
<% #survey.option_booleans.each do |question| %>
<%= question.topic %><br>
<%= radio_button "option_booleans_attributes[]", "answer[#{question.id}]", "true" %>是
<%= radio_button "option_booleans_attributes[]", "answer[#{question.id}]", "false" %>否<br>
<% end %>
But I don't know how to generate the 0 1 2 in the parameter..
about my survey.rb
class Survey < ActiveRecord::Base
has_many :option_booleans
accepts_nested_attributes_for :option_booleans
belongs_to :member
end
class OptionBoolean < ActiveRecord::Base
belongs_to :survey03
and OptionBoolean have topic:string and answer:boolean
I want to let user see the topic and update the answer

It seems you're missing several parts of your form:
#app/controllers/surveys_controller.rb
def new
#survey = Survey.new
#survey.option_booleans.build #-> creates ActiveRecord Object for your form
end
#app/views/surveys/new.html.erb
<%= form_for #survey do |f| %>
<%= f.fields_for :option_booleans do |option| %>
<% #survey.question_booleans.each do |question| %>
<%= question.topic %>
<%= f.radio_button "answer[#{question.id}]", "true" %>
<%= f.radio_button "answer[#{question.id}]", "false" %>
<% end %>
<% end %>
<% end %>
Although I don't quite understand how your system works
You have a survey with many options, but you're passing new attributes to create new options each time. Surely you'd have option_booleans as a join model, with options as an independent model, and:
#app/models/survery.rb
Class Survey < ActiveRecord::Base
has_many :option_booleans
has_many :options, through: :option_booleans
end

What I use now
<li><% #survey03.option_booleans.each do |question| %>
<%= question.topic %><br>
<%= radio_button "option_booleans_attributes[#{question.id}]", "answer", "true", :required => true %>
<%= radio_button "option_booleans_attributes[#{question.id}]", "answer", "false", :required => true %>
<% end %></li>
and in controller
params[:option_booleans_attributes].each do |option_id, attributes|
if option = OptionBoolean.find_by_id(option_id)
option.update_attributes(attributes)
end
end
and I know if I want to generate index just use
<% #survey.option_booleans.each_with_index do |question, index| %>
<%= question.topic %><br>
<%= radio_button "option_booleans_attributes[#{index}]", "answer[#{question.id}]", "true" %>
<%= radio_button "option_booleans_attributes[#{index}]", "answer[#{question.id}]", "false" %>
<% end %>

try select options like this:
#variable_with_booleans = [true, false]
<%= f.select :param, #variable_with_booleans %>
answer to your latest comment:
I don't sure, but try to edit your form
<%= form_for #question do |f| %>
<%= f.label :topic %>
<% #variable_with_booleans = [true, false] %>
<%= f.select :answer, #variable_with_booleans %>
<%= f.submit %>
<% end %>
and edit your strong params in controller,which contains this action

Related

Rails fields_for update not working (deleting the parent object)

I have fields_for form for update like below:
<%= form_for #cuisine, url: {action: "update" } do |f| %>
<%= f.text_area :name %>
<% #cuisine.ingredients.each do |ing| %>
<%= f.fields_for ing do |ingredient_fields|%>
<%= ingredient_fields.text_area :name, :value=> ing.name %>
<%= ingredient_fields.hidden_field :_destroy%>
<%= link_to_remove_fields 'Remove this ingredient', f %>
<% end %>
<% end %>
<% end %>
my cuisines_controller:
def update
#cuisine = Cuisine.find(params[:id])
if #cuisine.update_attributes(cuisine_params)
redirect_to root_path
else
redirect_to edit_cuisine_path
end
end
Though this shows the form correctly (showing forms filled with #cuisine and its ingredients' info), after reloading the page the #cuisine object gets deleted even when I don't push the submit button.
Any idea what's going on or how to update nested attributes using fields_for?
Thanks in advance.
First you should just use fields_for like this:
<%= f.fields_for :ingredients do |ingredient_fields|%>
<%= ingredient_fields.text_area :name %>
<%= ingredient_fields.hidden_field :_destroy %>
<%= link_to_remove_fields 'Remove this ingredient', f %>
<% end %>
Second you should first check to see if the cuisine_params in your controller permit those attributes:
params.require(:cuisine).permit(:name, ingredients_attributes:[:id, :name, :_destroy])
Lastly, make sure your model has this accepts_nested_attributes_for :ingredients, allow_destroy: true

fields_for duplicates during edit

I followed this railscast.
Controller: project_sub_types_controller.rb
def new
#svn_repos = ['svn_software','svn_hardware']
#project_sub_type = ProjectSubType.new
#project_sub_type.repositories.build
end
def edit
#svn_repos = ['svn_software','svn_hardware']
#project_sub_type = ProjectSubType.find(params[:id])
end
Model: project_sub_type.rb
class ProjectSubType < ActiveRecord::Base
belongs_to :project_type
has_many :repositories, :dependent => :destroy
def repositories_attributes=(repos_attributes)
repos_attributes.each do |attributes|
repositories.build(attributes)
end
end
end
View: _form.html.erb
<%= form_for #project_sub_type, :html => {:class => 'project_subtype_form'} do |f| %>
<%= f.label :name, "Project sub type name" %>
<%= f.text_field :name %>
<% for repos in #project_sub_type.repositories %>
<%= fields_for "project_sub_type[repositories_attributes][]", repos do |repos_form| %>
<% #svn_repos.each do |repos| %>
<%= repos_form.check_box :repos_name, {}, "#{repos}", nil %>
<%= h repos -%>
<% end %>
<% end %>
<% end %>
<%= f.submit "Save"%>
This works perfectly during creation of a new record. But Y does the fields_for duplicates during edit. During create I see 2 checkboxes but during edit there are 4 checkboxes which duplicates the other 2 checkboxes. What am I doing wrong?
Update : The more times I click on edit and the duplication increases by 1.
<% for repos in #project_sub_type.repositories %>
<%= fields_for "project_sub_type[repositories_attributes][]", repos do |repos_form| %>
<% #svn_repos.each do |repos| %>
<%= repos_form.check_box :repos_name, {}, "#{repos}", nil %>
<%= h repos -%>
<% end %>
<% end %>
<% end %>
Get rid of that and do:
<%= f.fields_for :repositories do |repo_form| %>
<% #svn_repos.each do |rep| %>
<%= repo_form.check_box :repos_name, {}, rep, nil %>
<%= h rep -%>
<% end %>
<% end %>
Also get rid of repositories_attributes= method in your model and add accepts_nested_attributes_for :repositories
The railscast you linked is 7 years old. :)

Rails Nested Resources - Many Objects, Same Model, One Form Without Existing Objects

I have a model Vendors which has many Products. I would like to add many Products at a time without showing the existing products that belong to the vendor.product relationship. I only want to display the form for new objects. Currently everything is working but on the add page I am getting all of the objects that are tied to the instance relationship which is #vendor.products. If I do not use that relationship in the form I do not get any fields.
Here is my new Product action:
'def new
#vendor = Vendor.find(params[:vendor_id])
5.times {#vendor.products.build}
end'
Here is my form:
<%= form_for #vendor do |f| %>
<%= f.fields_for :products do |g| %>
<p>
<%= g.label :name %>
<%= g.text_field :name %>
<%= g.label :category %>
<%= g.select :category, options_for_select(['Parts', 'Labor', 'Extras', 'Shop']) %><br>
</p>
<% end %>
<p><%= f.submit "Submit" %></p>
<% end %>
The Product Model:
class Product < ActiveRecord::Base
belongs_to :vendors
attr_accessible :name, :category, :vendor_id, :vendor_sku, :products
validates :name, :uniqueness => true
validates :category, :presence => true
validates :name, :presence =>true
end
Just to reiterate, I would only like to show the blank, newly built objects as opposed to all of the products tied to that #vendor 's relationship. I must be overlooking a form structure to get this done but I just have not been able to figure it out. Thanks for looking.
Only render the nested fields if the product in a new record.
<%= form_for #vendor do |f| %>
<%= f.fields_for :products do |g| %>
<% if g.object.new_record? %>
<p>
<%= g.label :name %>
<%= g.text_field :name %>
<%= g.label :category %>
<%= g.select :category, options_for_select(['Parts', 'Labor', 'Extras', 'Shop']) %><br>
</p>
<% end %>
<% end %>
<p><%= f.submit "Submit" %></p>
<% end %>

Submit into two tables with single form submit

Is There Any way we can submit into two tables in single rails form_for/simple_form_for which both the tables are associated to each other?
Example:-
<%= form_for #ob do |f| %>
<%= f.text_field :name %>
<%= f.text_field :another_col --> this is another table column(having association)
<%f.button :submit %>
<%end%>
The trick is to add accepts_nested_attributes_for to your parent model, and do as below
MODEL
class Ob < ActiveRecord::Base
has_many :foo
accepts_nested_attributes_for :foo, allow_destroy: true
end
ERB
<%= form_for #ob do |f| %>
<%= f.text_field :name %>
<% f.foo do |fo| %>
<%= fo.text_field :another_col %> <%=# this is another table column(having association)%>
<% end %>
<%f.button :submit %>
<%end%>
CONTROLLER
#your params would look like below
params = { ob: {
name: 'joe', foos_attributes: [
{ another_col: 'Bar' }
]
}}
Ob.create(params[:ob])

Rails 3 using fields_for in view doesn't work

I'm trying to implement master detail in a rails form with fields_for.
I have one model called Recipe:
class Recipe < ActiveRecord::Base
validates :name, :presence => true
validates :directions, :presence => true
has_many :recipe_ingredients
end
and one model called RecipeIngredient:
class RecipeIngredient < ActiveRecord::Base
belongs_to :recipe
#belongs_to :ingredient
end
In the new controller I populate the ingredients with three empty records like this:
def new
#recipe = Recipe.new
3.times {#recipe.recipe_ingredients.build}
# #ingredients = RecipeIngredient.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #recipe }
end
end
What I would like to do in the view is to output the recipes fields (which works ok) and the three fields for recipe ingredients. In the top part of the view I have this:
<%= form_for :rec do |f| %>
I then list the recipe fields which are displayed correctly, like:
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
I then try to display the ingredient lines but the code never seems to go into the fields_for section:
first try:
<% for ingredient in #recipe.recipe_ingredients %>
This prints out three times
<% fields_for "...", ingredient do |ingredient_form| %>
But this never prints out
<p>
Ingredient: <%= ingredient_form.text_field :description %>
</p>
<% end %>
<% end%>
I have three empty lines in recipe_ingredients and the for loop seems to iterate three times but the code within fields_for never triggers.
Second try:
<% for recipe_ingredient in #recipe.recipe_ingredients %>
b
<% fields_for "...", recipe_ingredient do |recipe_ingredient| %>
Rec: <%= recipe_ingredient.text_field :description %>
<% end %>
<% end %>
Third try (based on the answer here):
<% form_for :recipe do |f| %>
<% f.fields_for ingredients do |ingredient_form| %>
<p>
Ingredient: <%= ingredient_form.text_field :description %>
</p>
<% end %>
<% end %>
Is there something obvious I'm doing wrong?
You should use <%= instead of <% when using form_for and fields_for
The correct code should look like this:
<%= form_for :recipe do |f| %>
<%= f.fields_for :ingredients do |ingredient_form| %>
<p>
Ingredient: <%= ingredient_form.text_field :description %>
</p>
<% end %>
<% end %>
Switch it up to
<% form_for :recipe do |f| %>
<% f.fields_for :ingredients do |ingredient_form| %>
<p>
Ingredient: <%= ingredient_form.text_field :description %>
</p>
<% end %>
<% end %>

Resources