Can't mass-assign protected attributes: quantities - ruby-on-rails

I'm getting this error:
Can't mass-assign protected attributes: quantities
I looked up all the threads concerning this issue in the site, but couldn't find something to answer my problem. Here are the code snippets:
product.rb
class Product < ActiveRecord::Base
attr_accessible :name, :quantities_attributes
has_many :quantities
accepts_nested_attributes_for :quantities, :allow_destroy => :true,
:reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } }
new.html.erb
<% if #was_submitted %>
<%= form_for(:new_product_array, :url => products_path) do |f| %>
<% prefix ||= 0 %>
<% #new_product_array.each do |n| %>
<% n.quantities.build %>
<% prefix += 1 %>
<%= f.fields_for(prefix.to_s ) do |child| %>
<div class="field">
<%= child.label :name %><br />
<%= child.text_field :name%>
</div>
<%= render :partial => 'quantities/form',
:locals => {:form => child} %>
<% end %>
<% end %>
<div class="actions">
<%= submit_tag :submit %>
</div>
<% end %>
<% else %>
<%= form_tag new_product_path, :method => 'get' do %>
<p align=center>
How many Items are you Adding? (1-100)
<%= number_field_tag 'amount', 1, :in => 1...100 %>
</br>
To which storage?
<%= number_field_tag 'storage', 1, :in => 1...100 %>
<%= submit_tag "Next", :name => 'submitted' %>
</p>
<% end %>
<% end %>
<%= link_to 'Back', products_path %>
product_controller.rb
def new
#product = Product.new
if params['submitted']
#was_submitted = true
#amount_form = params['amount']
#new_product_array = []
(1..#amount_form.to_i).each do
#new_product_array << Product.new
end
#storage_form = params['storage']
else
#was_submitted = false
end
respond_to do |format|
format.html # new.html.erb
format.json { render :json => #product }
end
end
def create
i=0
logger.info params[:new_product_array].inspect
params[:new_product_array].each do |new_product|
if new_product.last[:name] != nil
#new_product_array[i] = Product.new(new_product.last)
#new_product_array[i].save
i+=1
end
end
redirect_to(products_path)
end
quantity.rb
class Quantity < ActiveRecord::Base
belongs_to :product
attr_accessible :amount, :storage
end
quantity/_form.html.erb
<%= form.fields_for :quantities do |quant| %>
<div class="field">
<%= quant.label :storage %><br />
<%= quant.number_field :storage %>
</div>
<div class="field">
<%= quant.label :amount %><br />
<%= quant.number_field :amount %>
</div>
<% unless quant.object.nil? || quant.object.new_record? %>
<div class="field">
<%= quant.label :_destroy, 'Remove:' %>
<%= quant.check_box :_destroy %>
</div>
<% end %>
<% end %>
Overall what Im trying to do, is ask the user how much products to add, then make a form with the number of fields the user specifies and with one submit button add all of the products, whereas when you add a product you also add a quantity record which holds more information on the product.

You need a line like this:
attr_accessible :name, :quantities_attributes, :quantities

You have very bad code, it can be much simplier 100%.
Your problem is that form dont' know nothing about your resource (product), so it can't render 'smartly' fields "quantities_attributes", it renders "quantities" instead.

Related

rails: nested-form doesn't render in view

I have models like this
post.rb
has_many :items
accepts_nested_attributes_for :items
item.rb
has_one :heading, dependent: :destroy
has_one :content, dependent: :destroy
has_one :link, dependent: :destroy
has_one :movie, dependent: :destroy
has_one :photo, dependent: :destroy
has_one :quate, dependent: :destroy
accepts_nested_attributes_for :heading
accepts_nested_attributes_for :content
accepts_nested_attributes_for :link
accepts_nested_attributes_for :movie
accepts_nested_attributes_for :photo
accepts_nested_attributes_for :quate
heading,content,link,movie,photo,quate.rb
belongs_to :item
posts_controller.rb
def new
#post = current_user.posts.build
end
def create
#post = current_user.posts.build(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'created!!' }
else
format.html { render :new }
end
end
def post_params
params.require(:post).permit(:title, :description, :image,:user_id,
items_attributes:[:id, :order,
heading_attributes:[:id, :head],
photo_attributes:[:id, :image, :title, :q_url],
movie_attributes:[:id, :y_url],
quate_attributes:[:id, :quate, :q_url, :q_title, :q_comment],
content_attributes:[:id, :content],
link_attributes:[:id, :url, :l_text],
twitter_attributes:[:id, :t_url]
])
end
posts/new_and_edit.html.erb
<%= form_for(#post) do |f| %>
<% if #post.errors.any? %>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :description%>
<%= f.text_field :description %>
<%= f.label :image %>
<%= f.file_field :image %>
<%= f.hidden_field :user_id %>
<%= f.submit %>
<%= render 'posts/item_form_fields', name: 'headings' %>
<%= render 'posts/item_form_fields', name: 'contents' %>
<%= render 'posts/item_form_fields', name: 'movies' %>
<%= render 'posts/item_form_fields', name: 'quates' %>
<%= render 'posts/item_form_fields', name: 'links' %>
<%= render 'posts/item_form_fields', name: 'photos' %>
posts/_item_form_fields.html.erb
<%= form_for(#post, remote: false) do |m| %>
<%= render 'items/form_fields', m: m, name: name %>
<%= m.submit "submit" %>
<% end %>
items/_form_fields.html.erb
<%= m.fields_for :items, #item do |b| %>
<%= b.hidden_field :order, value: '0' %>
<%= render "#{name}/form_fields", b: b %>
<% end %>
headings/_form_fields.html.erb
<%= b.fields_for :heading, #item.build_heading do |h| %>
<%= h.text_field :head %>
<% end %>
"I have a "_form_fields.html.erb" for content,link,movie, photo and quate as well. "
when I run rails server, the nested-models form doesn't show up on view.
Also I pressed "submit", console said that
param is missing or the value is empty: post
I don't get why its happen.
Do you have any idea?
Thanks
You need to correct some important things
In your posts#new action
def new
#post = current_user.posts.build
#item = #post.items.build
#item.build_heading
#item.build_content
#item.build_link
#item.build_movie
#item.build_photo
#item.build_quate
end
And your form code after all the changes should look like this
<%= form_for(#post) do |f| %>
<% if #post.errors.any? %>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :description%>
<%= f.text_field :description %>
<%= f.label :image %>
<%= f.file_field :image %>
<%= f.hidden_field :user_id %>
<%= f.fields_for #item do |m| %>
<%= render 'items/form_fields', m: m %>
<%= render 'headings/form_fields', m: m %>
<%= render 'contents/form_fields', m: m %>
<%= render 'movies/form_fields', m: m %>
<%= render 'quates/form_fields', m: m %>
<%= render 'links/form_fields', m: m %>
<%= render 'potos/form_fields', m: m %>
<% end %>
<%= f.submit %>
<% end %>
And you need to change the contents of partials like below
#items/_form_fields.html.erb
<%= m.hidden_field :order, value: '0' %>
#headings/_form_fields.html.erb
<%= m.fields_for :heading do |h| %>
<%= h.text_field :head %>
<% end %>
And the same for the remaining partials as well.

Rails 4 Permitted Params with nested attributes

Alright, been looking everywhere for this one. Tried all the solutions. Maybe someone can help on this.
So, I have a WebRequest model that has many WebSites. Each WebSite belongs to a WebRequest. My problem is in the nested form. Ive gone in an permitted the params (atleast, based on the documentation I have) and everything works fine until I go into the server logs. Posted below
class WebRequest < ActiveRecord::Base
has_many :web_sites
accepts_nested_attributes_for :web_sites
end
and here is the WebSite model
class WebSite < ActiveRecord::Base
belongs_to :web_request, dependent: :destroy
end
_form.html.erb
<% 1.times do %>
<%= f.fields_for :web_site do |ff| %>
<%= ff.input :url %>
<%= ff.input :description %>
<% end %>
<% end %>
WebRequests Controller
class WebRequestsController < ApplicationController
def new
#web_request = WebRequest.new
# #web_request.web_sites.build
end
def index
#web_requests = WebRequest.all
end
def create
#web_request = WebRequest.new(web_request_params)
respond_to do |format|
if #web_request.save
RequestMailer.web_request_submit(#web_request).deliver
format.html { render partial: 'success' }
format.json { render action: 'show', status: :created, location: #web_request }
else
format.html { render action: 'new' }
format.json { render json: #web_request.errors, status: :unprocessable_entity }
end
end
end
def web_request_params
params.require(:web_request).permit(:web_needs, :primary_goal, :secondary_goal, : :call_to_action, :hero_image, :image_count, :existing, :resources, :web_examples, :special_functions, :social_network, web_sites_attributes: [:id, :url, :description])
end
end
And here is the server log:
Started POST "/web_requests" for 127.0.0.1 at 2014-07-10 15:56:12 -0400
Processing by WebRequestsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"0iisNgGk/AhC4jRrp1cmKWVCBsCcSx5G2dueEI/+p2A=", "web_request"=>{"web_needs"=>"", "primary_goal"=>"", "secondary_goal"=>"", "call_to_action"=>"", "hero_image"=>"", "image_count"=>"", "existing"=>"", "web_site"=>{"url"=>"TROLL", "description"=>"TROLL"}, "resources"=>"", "special_functions"=>"", "social_network"=>""}, "commit"=>"Create Web request"}
Unpermitted parameters: web_site
Notice at how the form fields get passed but they get restricted out of making it to the DB.
THANKS!
Update::
Here is the full form path:
<%= simple_form_for(#web_request) do |f| %>
<% if #web_request.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#web_request.errors.count, "error") %>
prohibited this Web Request from being saved:</h2>
<ul>
<% #web_request.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="container">
<div class="field">
<%= f.input :web_needs, label: 'What web needs do you have?' %>
</div>
<div class="container"><h5>Please list below 5 URL's and explanations of why you like them.</h5></div>
<% 1.times do %>
<%= f.fields_for :web_sites do |ff| %>
<div class="field">
<%= ff.input :url, label: "URL of example site" %>
</div>
<div class="field">
<%= ff.input :description, label: "Description of example site" %>
</div>
<% end %>
<% end %>
<div class="field">
<%= f.input :resources, label: 'Will you be providing any kind of resource on this page? e.g. chord chart download.' %></br>
</div>
</div>
<div class="actions">
<%= f.button :submit, :class => "button" %>
</div>
</div>
<% end %>
Update::Full error log
undefined method `url' for #<ActiveRecord::Associations::CollectionProxy []>
The line is here
<% 1.times do %>
<%= f.simple_fields_for :web_site, #web_request.web_sites do |ff| %>
<div class="field">
<%= ff.input :url, label: "URL of example site" %> <--ERROR HERE on ':url'
</div>
<div class="field">
<%= ff.input :description, label: "Description of example site" %>
</div>
<% end %>
Add to controller in new action:
def new
#web_request = WebRequest.new
#web_site = #web_request.web_sites.build
end
and form:
<%= f.simple_fields_for #web_site do |ff| %>
<%= ff.input :url %>
<%= ff.input :description %>
<% end %>
<% end %>
and web_request_params:
def web_request_params
params.require(:web_request).permit(:web_needs,
:primary_goal,
:secondary_goal,
:call_to_action,
:hero_image,
:image_count,
:existing,
:resources,
:web_examples,
:special_functions,
:social_network,
{ web_sites: [:id, :url, :description] })
end
In your controller in web_request_params change web_sites_attributes for web_site_attributes
In your controller remove the comment from #web_request.web_sites.build
In your view remove 1.times do
In yor form change f.fields_for :web_sites do |ff| with f.simple_fields_for :web_sites do |ff|

unable to create or update a belongs_to record in Rails 4

I'm new to Rails and struggling to get my belongs_to association right. I have an app where a painting belongs to an artist and an artist can have_many paintings. I can create and edit my paintings, however I can not edit or create artists except through the console. Through much Googling I feel I have got myself turned around. Any help would be much appreciated!
Here's my routes.rb file:
MuseumApp::Application.routes.draw do
resources :paintings
resources :paintings do
resources :artists
resources :museums
end
root 'paintings#index'
end
Here's my paintings Controller
def show
#painting = Painting.find params[:id]
end
def new
#painting = Painting.new
##artist = Artist.new
end
def create
safe_painting_params = params.require(:painting).permit(:title, :image)
#painting = Painting.new safe_painting_params
if #painting.save
redirect_to #painting
else
render :new
end
end
def destroy
#painting = Painting.find(params[:id])
#painting.destroy
redirect_to action: :index
end
def edit
#painting = Painting.find(params[:id])
end
def update
#painting = Painting.find(params[:id])
if #painting.update_attributes(params[:painting].permit(:title, :image)) #safe_params
redirect_to #painting
else
render :edit
end
end
Here's the form in my paintings view:
<%= form_for(#painting) do |f| %>
<fieldset>
<legend>painting</legend>
<div>
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<div>
<%= f.label :image %>
<%= f.text_field :image %>
</div>
<%= form_for([#painting,#painting.create_artist]) do |f| %>
<div>
<%= f.label :Artist %>
<%= f.text_field :name %>
</div>
</fieldset>
<%= f.submit %>
<% end %>
<% end %>
Artists Controller:
class ArtistsController < ApplicationController
def index
#artists = Artist.all
#artists = params[:q] ? Artist.search_for(params[:q]) : Artist.all
end
def show
#artist = Artist.find params[:id]
end
def new
#artist = Artist.new
end
def create
#painting = Painting.find(params[:painting_id])
#artist = #painting.create_artist(artist_params)
redirect_to painting_path(#painting)
end
def destroy
#artist = Artist.find(params[:id])
#Artist.destroy
redirect_to action: :index
end
def edit
#artist = Artist.find(params[:id])
end
def update
#painting = Painting.find(params[:painting_id])
#artist = #artist.update_attributes(artist_params)
redirect_to painting_path(#painting)
end
end
private
def artist_params
params.require(:artist).permit(:name)
end
Index view:
<h1> Hello and Welcome to Museum App</h1>
<h3><%= link_to "+ Add To Your Collection", new_painting_artist_path %></h3>
<%= form_tag '/', method: :get do %>
<%= search_field_tag :q, params[:q] %>
<%= submit_tag "Search" %>
<% end %>
<br>
<div id="paintings">
<ul>
<% #paintings.each do |painting| %>
<li><%= link_to painting.title, {action: :show, id:painting.id} %> by <%= painting.artist_name %></li>
<div id = "img">
<br><%= link_to (image_tag painting.image), painting.image %><br>
</div>
<%= link_to "Edit", edit_painting_path(id: painting.id) %>
||
<%= link_to 'Destroy', {action: :destroy, id: painting.id},method: :delete, data: {confirm: 'Are you sure?'} %>
<% end %>
</ul>
</div>
In your case you should use accepts_nested_attributes_for and fields_for to achieve this.
Artist
has_many :paintings, :dependent => :destroy
accepts_nested_attributes_for :paintings
Painting
belongs_to :artist
And also you should try creating artist with paintings like this
form_for(#artist) do |f| %>
<fieldset>
<legend>Artist</legend>
<%= f.label :Artist %>
<%= f.text_field :name %>
<%= fields_for :paintings, #artist.paintings do |artist_paintings| %>
<%= artist_paintings.label :title %>
<%= artist_paintings.text_field :title %>
<%= artist_paintings.label :image %>
<%= artsist_paintings.text_field :image %>
</fieldset>
<%= f.submit %>
<% end %>
Note:
You should be having your Artist Controller with at least new,create,edit and update methods defined in it to achieve this.
Edit
Try the reverse
Artist
has_many :paintings, :dependent => :destroy
Painting
belongs_to :artist
accepts_nested_attributes_for :paintings
form_for(#painting) do |f| %>
<fieldset>
<legend>Painting</legend>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :image %>
<%= f.text_field :image %>
<%= fields_for :artists, #painting.artists do |ff| %>
<%= ff.label :Artist %>
<%= ff.text_field :name %>
</fieldset>
<%= f.submit %>
<% end %>
Put this form in paintings views.

Ruby Rails submit two forms in one click

I have these forms:
<%= form_for(#user) do |f| %>
<div>
<%= f.number_field :money, :value => #user.money %>
</div>
<% end %>
and
<%= form_for #product, :url => product_path, :html => { :multipart => true } do |f| %>
<div>
<%= f.label :count, 'How Many product?' %><br />
<%= f.number_field :count, :value => "1" %>
</div>
<div>
<%= f.submit('submit') %>
</div>
<% end %>
is there any way to submit this two at once when clicking submit button ? Thanks!
A service object might be a good way to approach this.
class Order
include ActiveModel::Model
attr_accessor :money, :count
def initialize(user=nil, product=nil)
#user = user
#product = product
#money = user.money
#count = 1
end
def persisted?
false
end
def save
// this code needs to save to db
end
end

NoMethodError Rails multiple file uploads

I am working on getting multiple file uploads working for an model in my application, I have included the code below:
delivers_controller.rb
# POST /delivers
def create
#deliver = Deliver.new(params[:deliver])
process_file_uploads(#deliver)
if #deliver.save
flash[:notice] = 'Task was successfully created.'
redirect_to(#deliver)
else
render :action => "new"
end
end
protected
def process_file_uploads(deliver)
i = 0
while params[:attachment]['file_'+i.to_s] != "" && !params[:attachment]['file_'+i.to_s].nil?
deliver.assets.build(:data => params[:attachment]['file_'+i.to_s])
i += 1
end
end
deliver.rb
has_many :assets, :as => :attachable, :dependent => :destroy
validate :validate_attachments
Max_Attachments = 5
Max_Attachment_Size = 5.megabyte
def validate_attachments
errors.add_to_base("Too many attachments - maximum is #{Max_Attachments}") if assets.length > Max_Attachments
assets.each {|a| errors.add_to_base("#{a.name} is over #{Max_Attachment_Size/1.megabyte}MB") if a.file_size > Max_Attachment_Size}
end
assets_controller.rb
class AssetsController < ApplicationController
def show
asset = Asset.find(params[:id])
# do security check here
send_file asset.data.path, :type => asset.data_content_type
end
def destroy
asset = Asset.find(params[:id])
#asset_id = asset.id.to_s
#allowed = Deliver::Max_Attachments - asset.attachable.assets.count
asset.destroy
end
end
asset.rb
class Asset < ActiveRecord::Base
has_attached_file :data,
belongs_to :attachable, :polymorphic => true
def url(*args)
data.url(*args)
end
def name
data_file_name
end
def content_type
data_content_type
end
def file_size
data_file_size
end
end
Whenever I create a new deliver item and try to attach any files I get the following error:
NoMethodError in DeliversController#create
You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]
/Users/danny/Dropbox/SVN/railsapps/macandco/surveymanager/trunk/app/controllers/delivers_controller.rb:60:in `process_file_uploads'
/Users/danny/Dropbox/SVN/railsapps/macandco/surveymanager/trunk/app/controllers/delivers_controller.rb:46:in `create'
new.html.erb (Deliver view)
<% content_for :header do -%>
Deliver Repositories
<% end -%>
<% form_for(#deliver, :html => { :multipart => true }) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :caseref %><br />
<%= f.text_field :caseref %>
</p>
<p>
<%= f.label :casesubject %><br />
<%= f.text_area :casesubject %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_area :description %>
</p>
<p>Pending Attachments: (Max of <%= Deliver::Max_Attachments %> each under <%= Deliver::Max_Attachment_Size/1.megabyte%>MB)
<% if #deliver.assets.count >= Deliver::Max_Attachments %>
<input id="newfile_data" type="file" disabled />
<% else %>
<input id="newfile_data" type="file" />
<% end %>
<div id="attachment_list"><ul id="pending_files"></ul></div>
</p>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
<%= link_to 'Back', delivers_path %>
Show.html.erb (Delivers view)
<% content_for :header do -%>
Deliver Repositories
<% end -%>
<p>
<b>Title:</b>
<%=h #deliver.caseref %>
</p>
<p>
<b>Body:</b>
<%=h #deliver.casesubject %>
</p>
<p><b>Attached Files:</b><div id="attachment_list"><%= render :partial => "attachment", :collection => #deliver.assets %></div></p>
<%= link_to 'Edit', edit_deliver_path(#deliver) %> | <%= link_to 'Back', deliver_path %>
<%- if logged_in? %>
<%= link_to 'Edit', edit_deliver_path(#deliver) %> |
<%= link_to 'Back', delivers_path %>
<% end %>
_attachment.html.erb (Delivers view)
<% if !attachment.id.nil? %><li id='attachment_<%=attachment.id %>'><a href='<%=attachment.url %>'><%=attachment.name %></a> (<%=attachment.file_size/1.kilobyte %>KB)
<%= link_to_remote "Remove", :url => asset_path(:id => attachment), :method => :delete, :html => { :title => "Remove this attachment", :id => "remove" } %></li>
<% end %>
I have been banging my head against the wall with the error all day, if anyone can shed some light on it, I would be eternally grateful!
Thanks,
Danny
The error message indicates that params[:attachment] is nil inside process_file_uploads(), which causes params[:attachment]['file_'+i.to_s] to raise an exception.
This happens because there's no field named attachment in the form in new.html.erb.

Resources