Rails 4 Select Menu action cannot be nil error - ruby-on-rails

I'm trying to use the Rails form_for and collection select tags to populate a select menu from a database table. When the user hits the submit button there selection will be reflected in my shopping cat table (through the join table CampaignItems). Currently I'm getting a:
First argument in form cannot contain nil or be empty error
The view is in my store index.html.erb file.
Here is my view:
<% form_for #duration do |f| %>
<%= f.collection_select :duration, Duration.all, :id, :name %>
<%= f.submit 'Submit', campaign_items_path(duration_id: duration) %>
<% end %>
My Durations controller:
def index
#durations = Duration.all
end
def new
#duration = Duration.new
end
My Store Controller:
def index
#products = Product.order(:title)
#cart= current_cart
#durations = Duration.all
end

First argument in form cannot contain nil or be empty error
The problem is you have declared #durations = Duration.all in your index action,but you are using #duration in the form.You should be using #durations.
It should be like this
<% form_for #durations do |f| %>
<%= f.collection_select :duration, Duration.all, :id, :name %
<%= f.submit 'Submit', campaign_items_path(duration_id: duration) %>
<% end %>

Related

Redirecting to "show" view of a model object when searched by attributes (NOT id)

I have a form where users look for a particular bill by some attributes of that bill, namely the "Congress Number", "Bill Type", and "Bill Number", as in 114-H.R.-67 . I want to "show" the appropriate bill, but to do that I have get the appropriate bill model in a separate action which I've called "find_by_attributes". Inside this action I perform:
#bill = Bill.find_by( params ).first
which correctly acquires the appropriate bill's id.
Now I simply want to redirect to the "show" method of this bill, as in the url
".../bills/[#bill.id]"
As of right now, at the end of my "find_by_attributes" action I do
redirect_to bills_path(#bill)
which correctly loads the show.html.erb with #bill, but does not change the url (the url is still shows the "find_by_attributes" action followed by a long query-string, instead of the clean "/bills/[:bill_id]".
How can I restructure my code to achieve the neat redirect that I desire?
Full code below:
THE FORM
<%= form_tag("bills/find_or_create", :method => :get ) do |f| %>
<%# render 'shared/error_messages', object: f.object %>
<%= fields_for :bill do |ff| %>
<%= ff.label :congress, 'Congress (i.e. 114)' %>
<%= ff.number_field :congress, class: 'form-control' %>
<%= ff.select :bill_type, options_for_select(
[['House of Representatives', 'hr'],
['Senate', 's'],
['House Joint Resolution', 'hjres'],
['Senate Joint Resolution', 'sjres'],
['House Concurrent Resolution', 'hconres'],
['Senate Concurrent Resolution', 'sconres'],
['House Resolution', 'hres'],
['Senate Resolution', 'sres']]
)
%>
<%= ff.label :bill_number, 'Bill number (i.e. 67)' %>
<%= ff.number_field :bill_number, class: 'form-control' %>
<% end %>
<%= submit_tag "Submit", class: "btn btn-primary" %>
<% end %>
THE CONTROLLER ACTIONS
def find_by_attributes
#bill = Bill.where(bill_params).first_or_create(bill_attributes)
redirect_to bills_path(#bill)
end
def show
puts bill_params
if params[:bill]
#bill = Bill.where(bill_params).first_or_create do |bill|
bill.attributes = bill_attributes
end
else
#bill = Bill.find(params[:id])
end
#subjects = Subject.where("bill_id = ?", #bill[:id])
#bill_comments = Comment.where("target = ?", #bill[:id])
end
ROUTES FILE
...
resources :bills do
get :find_by_attributes
end
...
EDIT
I make use of the turbolinks gem in my rails application.
the thing I see here is that you are calling to
redirect_to bills_path(#bill)
that in theory is not the show path, you just need to remove the "s"
redirect_to bill_path(#bill)
and as a side comment, in this line, you don't need the first part, because find_b, finds the first record matching the specified conditions, you can remove that part.
#bill = Bill.find_by( params )

Given a Model enum, how to create a radio button group

I have a model like:
class User < ActiveRecord::Base
enum :status [:banned, :registered, :trial, :pending]
end
On my edit page, I want to show a list of 4 radio buttons and pre-select the radio button that is currently set for a user.
How can I do this?
<%= form_for #user do |f| %>
<%= f.collection_radio_buttons :status, User.statuses, :first, :first %>
<%= f.submit %>
<% end %>
Ref
Rails creates a class method using the pluralized attribute name when you use enum. The method returns a key value pair of strings you've defined and what integers they map to. So, you could do something like this:
<% User.status.keys.each do |status| %>
<%= f.radio_button :status, status %>
<%= f.label status.to_sym %>
<% end %>

Rails - Failing to pass parameters from New to Create in the controller

This is an excerpt from a view -
<%= #user.id %> is the user id
<%= #book.id %> is the book id
<div class="field">
<%= f.select :contribtype, options_for_select(Contribution::CONTRIB_TYPES) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I have passed the parameters for the user and the book from previous views, such that I have
http://localhost:3000/contributions/new?book_id=1&user_id=5
as the URL for the form. The correct user_id and book_id are showing up on the page.
I have the following in the controller -
def new
#user = User.find_by_id(params[:user_id])
#book = Book.find_by_id(params[:book_id])
#contribution = Contribution.new(params[book_id: #book.id, user_id: #user.id])
end
def create
#contribution = Contribution.new(contribution_params)
....
... but the user_id and book_id are not being captured in the object when it is created. I don't get any error, the data is simply not being set in the new object. Should I by passing parameters in the create action differently?
I'd use hidden fields as a quick fix:
#contribution = Contribution.new
in html:
<%= f.hidden_field :user_id, value: #user.id %>
<%= f.hidden_field :book_id, value: #book.id %>
be sure to permit those fields in your contribution_params

Create with multiple params issue

I have a controller that looks like this:
def new
#columns = Column.where(:table_id => #table.id)
#row = Row.new(id: #table.id)
end
def create
row_params.each do |row_param|
#row = Row.new(row_param)
#row.column_id = params["column_id"]
if #row.save
redirect_to collection_rows_path, notice: 'item was successfully created.'
else
render action: 'new'
end
end
end
I have a form that looks like:
<%= form_for [#table, #row] do |f| %>
<% #columns.each do |column| %>
<%= column.id %>
<%= hidden_field_tag :column_id, column.id %>
<%= f.label :data %><br>
<%= f.text_field :data %>
<% end %>
<%= f.submit %>
<% end %>
Basically, I'm trying to send multiple params and have them inserted with the column. But I keep getting this error:
undefined methodstringify_keys' for ["data", "No"]:Array` when there is two columns which means there is two text fields and I insert "Hello" in the first one, and "No" in the second.
Two things: Why is it only reading the "No" on the second one instead of both the "Hello" and "No"? And also why am I getting this error?
Thanks for all help!
Answers to your questions:
It is only reading "No" which is your input in the last "Data" text_field since the two text_fields generated in your form_for save their input value in the same params key which is params[:row][:data]. What happens then is the latest value saved to the params[:row][:data] key overrides any previous value it had.
The error undefined method stringify_keys' for ["data", "No"]:Array happens because you create 2 text_fields with the same name which is :data. When you submit the form, an Array is being submitted instead of a String that Rails expects when using text_field.
Solution to your problem:
This seems like an ideal use case for using a nested model form. Basing on your code, it looks like Row belongs_to Table. So in your Table model you'll need to add this code:
#app/models/table.rb
accepts_nested_attributes_for :row
Then add the following code in your RowsController:
#app/controllers/rows_controller.rb
def new
#columns = Column.where(:table_id => #table.id)
#columns.each do |column|
#table.rows.build(column_id: column.id)
end
end
def create
#table = Table.new(table_params)
if #table.save
redirect_to collection_rows_path, notice: 'item was successfully created.'
else
render :new
end
end
private
def table_params
params.require(:table).permit(rows_attributes: [:data, :column_id])
end
Then in your 'rows#new' view:
#app/views/rows/new.html.erb
<%= form_for #table, url: rows_path ,method: :post do |f| %>
<%= f.fields_for :rows do |r| %>
<%= r.object.column.name %>
<%= r.hidden_field :column_id, value: r.object.column_id %>
<%= r.label :data %><br>
<%= r.text_field :data %>
<% end %>
<%= f.submit %>
<% end %>
What the above code will do is allow you to create multiple rows for a column according to the number of columns the table has. This won't work though if a #table has no #columns yet. This assumes that you've created #columns for the #table already. Basing on your code though, it seems like that's already what you're doing.
you want to store 'data' as array in Row
In Rails model Row add
serialize :data, Array
in view
text_field_tag 'row[data][]'
You are getting only 'No' because form for does not know its an array so , it picks the last one And you are getting this error because rails does not know you want to store it as array , it excepts a string but got an array instead.

Submitting multiple rows into a database using a single form

I've created a rails app where a user chooses their preference between different vegetables. The database is formatted as follows:
Prefid (key)
Userid
veg1
veg2
preference
The form follows a format --
<%= form_for :pick do |f| %>
<%= f.collection_select( :id, Players.all, :id, :name) %>
<%= f.radio_button(pref.id, veg.veg1) %>
<%= f.radio_button(pref.id, veg.veg2) %>
<%= f.submit %>
<% end %>
Right now, when the form is submitted, I have this as my create method --
def create
#prefs = Prefs.new()
#prefs[:player_id] = post_params[:id]
post_params.delete(:id)
post_params.each do |key, value|
#prefs.games_id = key
#prefs.pick = value
#prefs.save
end
redirect_to #picks
end
This method doesn't work. It only submits the first pick into the database. I've read a few different ways to do this, but none of them really follow the same format as my application.

Resources