Rails 4.2 Create ActiveRecord object with nested params - ruby-on-rails

Does anybody know how to handle these attributes in the controllers new and create action?
(byebug) params
{"utf8"=>"V", "authenticity_token"=>"Wex9nnFigOviySzjfPN6zw==",
"recipe"=>{"name"=>"Cupcake"},
"name"=>{"ingredient_id"=>"2"},
"quantity"=>{"amount"=>"zwei"},
"commit"=>"Create", "controller"=>"recipes", "action"=>"create"}
I don't know how to create the quantities record with the value from Ingredient in recipe#new
("name"=>{"ingredient_id"=>"2")
Two records should be created (Recipe and Quantity).
Recipe
name
Quantity
ingredient_id
recipe_id
amount
Ingredient
name
class Recipe < ActiveRecord::Base
belongs_to :user
has_many :quantities
has_many :ingredients, through: :quantities
accepts_nested_attributes_for :quantities, :reject_if => :all_blank, :allow_destroy => true
accepts_nested_attributes_for :ingredients
end
class Ingredient < ActiveRecord::Base
has_many :quantities
has_many :recipes, :through => :quantities
end
class Quantity < ActiveRecord::Base
belongs_to :recipe
belongs_to :ingredient
accepts_nested_attributes_for :ingredient, :reject_if => :all_blank
end
<%= form_for(#recipe) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= form_for(#recipe.quantities.build) do |g| %>
<%= select("name", "ingredient_id", Ingredient.all.collect {|p| [ p.name, p.id ] }, {include_blank: 'Auswählen'}) %>
<%= g.label :amount %>
<%= g.text_field :amount %>
<%= g.submit "Create" %>
<% end %>
<% end %>

I replaced:
<%= form_for(#recipe.quantities.build) do |g| %>
with:
<%= f.fields_for :quantities, #recipe.quantities.build do |g| %>
And put submit action to form level after fields_for:
<%= f.submit "Create" %>

Related

Creating an object with a nested form - how to pass params to controller

I'm really struggling with how to make a form create an object, and two sub-objects. My Guide has_one City_obj and has_one Country_obj.
guide.rb
class Guide < ActiveRecord::Base
has_one :city_obj, dependent: :destroy
has_one :country_obj, dependent: :destroy
belongs_to :user
has_many :guide_pics, dependent: :destroy
accepts_nested_attributes_for :city_obj, :country_obj
end
city_obj.rb
class CityObj < ActiveRecord::Base
belongs_to :guide
belongs_to :country_obj
end
country_obj.rb
class CountryObj < ActiveRecord::Base
belongs_to :guides
has_many :city_obj, dependent: :destroy
end
new.html
<%= form_for(#guide) do |f| %>
<%= render 'new_form_part', f: f, field: 'name', label: 'name', type: 'text_field',
<%= f.fields_for :country_obj, #guide.country_obj do |p| %>
<%= f.text_field :name, class: 'form-control' %>
<% end %>
<%= f.fields_for :city_obj, #guide.city_obj do |p| %>
<%= f.text_field :name, class: 'form-control' %>
<% end %>
<% end %>
In my controller create method, I get
params[:guide] = {"name"="whatever is submitted for city"}
That's because the partial that sets :name is being overwritten by the text_fields below. How can I get them to pass params[:guide][:city_obj][:name] and params[:guide][:country_obj][:name]?
UPDATE: There is a typo. I should be using p.text_field, not f.text_field

Using rails 4, how to deeply nest resources in a parent form

Writing a recipe app. Having a hell of a time getting this down.
My Models:
Recipe
has_many :recipe_ingredients
has_many :ingredients, through: :recipe_ingredients
Recipe_Ingredient
belongs_to :recipe
belongs_to :ingredient
Ingredient
has_many :recipe_ingredients, :dependent => :destroy
has_many :recipes, through: :recipe_ingredients
My routes are simple
resources :recipes // AND A FEW RANDOM OTHERS
In my Recipes Controller:
def new
#recipe = Recipe.new
recipe_ingredients = #recipe.recipe_ingredient.build
recipe_ingredients.ingredient.build
end
My Recipe Form:
<%= simple_form_for #recipe do |r| %>
<%= r.input :title, label: 'Recipe Name:' %>
<%= r.input :description, label: 'Recipe Description' %>
<%= r.simple_fields_for :recipe_ingredients do |ri| %>
<%= ri.input :quantity, label: "Quantity" %>
<%= ri.simple_fields_for :ingredients do |i| %>
<%= i.input :name, label: "name" %>
<% end %>
<% end %>
<%= r.button :submit %>
<% end %>
Not sure what I am doing wrong. The error is:
undefined method `recipe_ingredient' for #<Recipe:0x000001034d3650>
any ideas? Spent 2 nights on this.
The particular error seems to come from referencing #recipe.recipe_ingredient (singular), which should be pluralized, since it is a has_many relation. Try this in your RecipeController#new:
recipe_ingredients = #recipe.recipe_ingredients.build
Then, for the recipe_ingredients.ingredient, try using build_association instead:
recipe_ingredients.build_ingredient

Ruby on Rails unpermitted parameters with has many through

I have order and products, and a join table called orders_products, the order has many products through order_products and accepts nested attributed for it.
When I try to save it keeps saying unpermitted paramters: order_product
Params
def order_params
params.require(:order).permit(:id, :order_number, :customer_id, {order_products_attributes: [:id, :order, :product, :quantity ]}, {:product_ids => []})
end
Order model
class Order < ActiveRecord::Base
belongs_to :customer
has_many :order_products, class_name: "OrderProduct"
has_many :products, through: :order_products
accepts_nested_attributes_for :order_products, :allow_destroy => true
end
Order Product model
class OrderProduct < ActiveRecord::Base
belongs_to :product
belongs_to :order
end
Order controller new action
def new
#order = Order.new
#order.order_products.build
end
Order Form
<%= simple_form_for #order do |f| %>
<%= f.input :order_number %>
<%= f.fields_for :order_product do |fa| %>
<%= fa.input :product, collection: Product.all %>
<%= fa.input :quantity %>
<% end %>
<%= f.association :customer, as: :select %>
<%= f.submit %>
<% end %>
Params hash - {"utf8"=>"√","authenticity_token"=>"yBrH91u0OHTSPnCFO/484Ff6CRtyRLSg5AKD1Lc33k4=", "order"=>{"order_number"=>"0121", "order_product"=>{"product"=>"4", "quantity"=>"5"}, "customer_id"=>"3"}, "commit"=>"Create Order"}
Unpermitted parameters: order_product
you are missing s here:
<%= f.fields_for :order_products do |fa| %>

form_for with ckeckbox_tag from other model

I'm new to rails and just cant get that problem solved.
i have 3 models. Orders, Products and LineItems.
I want to have a order form with checkboxes for each product. User selects appropriate products and submits the order.
I cannot get the form to create the correct hash.
class Order < ActiveRecord::Base
attr_accessible :account_id, :user_id
has_many :line_items, :dependent => :destroy
end
class LineItem < ActiveRecord::Base
attr_accessible :account_id, :product_id, :order_id
belongs_to :orders
belongs_to :product
end
Here the view:
<%= form_for 'line_items[]' do |f| %>
<%= f.select :account_id, options_from_collection_for_select( Account.all,
:id, :name ), :prompt => 'Select Account' %>
<% Product.all.each do |product| %>
<div>
<%= check_box_tag 'line_items[product_ids][]', product.id %>
</div>
<% end -%>
<div>
<%= f.submit 'save' %>
</div>
thanks!
You would need to use accepts_nested_attributes_for in your model to enable nested atributes from associated models. You may also want to check out this railscast and adapt to your needs.
For example in the orders model:
class Order < ActiveRecord::Base
attr_accessible :account_id, :user_id
has_many :products #This makes the association to products
has_many :line_items, :dependent => :destroy
accepts_nested_attributes_for :products #This allows the attributes from products accessible
end
Then the form could be:
<%= form_for #order do |f| %>
<%= f.select :account_id, options_from_collection_for_select( Account.all,
:id, :name ), :prompt => 'Select Account' %>
<%= f.fields_for :product do |product_form| %>
<%= product_form.check_box :id %>
<% end %>
<%= f.submit %>
<% end %>

ruby on rails - presenting many to many relation

I have recipe and ingredient in a many to many relation.
I have defined the following commands in my presentation.
<div>
<%= render :partial => 'ingredients/form',
:locals => {:form => recipe_form} %>
</div>
the partial begins with
<%= form_for(#ingredient) do |ingredient_form| %>
but received #ingredient nill.
Then I tried
<%= recipe_form.fields_for :ingredients do |builder| %>
<%= render 'ingredient_fields', f: builder %>
<% end %>
where my render was
<p class="fields">
<%= f.text_field :name %>
<%= f.hidden_field :_destroy %>
</p>
but nothing was printed.
then I tried
<% #recipe.ingredients.each do |ingredient| %>
<%= ingredient.name %>
<% end %>
and only then all of the ingredients were printed.
What was I doing wrong in the previous tries ?
Thank you.
my ingredient recipe relation defined as follows
class Ingredient < ActiveRecord::Base
has_many :ingredient_recipes
has_many :recipes, :through => :ingredient_recipes
...
class Recipe < ActiveRecord::Base
has_many :ingredient_recipes
has_many :ingredients, :through => :ingredient_recipes
...
accepts_nested_attributes_for :ingredient_recipes ,:reject_if => lambda { |a| a[:content].blank?}
class IngredientRecipe < ActiveRecord::Base
attr_accessible :created_at, :ingredient_id, :order, :recipe_id
belongs_to :recipe
belongs_to :ingredient
end
You don't exactly specify what you are trying to do, so I am presuming you have a page that shows a recipe, with many ingredients that can be edited and added to. In your controller you have something like:
class RecipeController < ApplicationController
def edit
#recipe = Recipe.find(params[:id]
end
end
I am also presuming that you are looking to have a form that post backs to the create action. I therefore think you want a form like this:
<%= form_for #recipe do |form| %>
<%= label_for :name %>
<%= text_field :name %>
<%= form.fields_for :ingredients do |ingredients_fields| %>
<div class="ingredient">
<%= f.text_field :name %>
<%= f.hidden_field :_destroy %>
</div>
<% end %>
<% end %>
Also, change your recipe to accept nested attributes for ingredients, not ingredient_recipes:
class Recipe < ActiveRecord::Base
has_many :ingredient_recipes
has_many :ingredients, :through => :ingredient_recipes
...
accepts_nested_attributes_for :ingredients, :reject_if => lambda { |a| a[:content].blank?}
And finally, add attr_accessible for your content:
class Ingredient < ActiveRecord::Base
attr_accessible :content
...
Does that work for you?

Resources