Passing all input as single params - ruby-on-rails

I have created a search form
<%= form_tag url_for(:action => "index") do %>
<%= text_field_tag 'fromdate' %>
<%= text_field_tag 'todate' %>
<%= submit_tag 'Search' %>
<% end %>
I need to pass all these values as a single params in my controller to model. This is my controller
def index
#client = Customer.search
#something like this #client = Customer.search(as_single_params)
respond_to do |format|
format.html
end
end
How can I do this?

You can do this in your view:
<%= text_field_tag "some_fields[]" %>
<%= text_field_tag "some_fields[]" %>
<%= text_field_tag "some_fields[]" %>
Then in your controller simply retrieve the values using:
some_fields = params[:some_fields] # this is an array
If you pass values as keys, Rails will give you a Hash:
<%= text_field_tag "some_fields[fromdate]" %>
<%= text_field_tag "some_fields[todate]" %>
In your controller you can do this now:
#clients = Customer.search(params[:some_fields])
^
I added an s to #client since you'll have probably more than one clients matching your criteria.

When you submit your form, all of the parameters you selected will be passed to the controller in the params hash. For example, params[:fromdate] and params[:todate].
In your controller, if your params hash contains only Customer fields you want to search on (i.e., the form only has Customer fields defined, then you can do:
def index
#clients = Customer.where(params)
respond_to do |format|
format.html
end
end
Note that I show #clients since where will return a collection. You can select the first one (especially if you're sure there's only one) by doing this:
#client = Customer.where(params).try(:first)

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 )

Ruby on Rails: new params keep showing as "permitted: false"

I've been writing a new RoR app for practice. This is a basic app that is supposed to function as a lookup page for animals.
I've been working on the Create/New functions in the controller for my page. I would like to make it so that a user can enter in an animal, and have the animal save to the SQL database. Afterwards, the page should redirect to the newly created animal page.
Here's my animals_controller.rb:
class AnimalsController < ApplicationController
def index
#animals = Animal.all
end
def show
#animal = Animal.find(params[:id])
end
def new
end
def create
# render plain: params[:animal].inspect
#animal = Animal.new(animal_params)
#animal.save
redirect_to #animal
end
private def animal_params
params.require(:animal).permit(:name, :scientific_name, :range)
end
end
Here is my views/animals/new.html.erb:
<h1> Add Animal </h1>
<%= form_for :animal, url: animals_path do |f| %>
<p>
<%= f.label :name %> <br>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :scientific_name %> <br>
<%= f.text_field :scientific_name %>
</p>
<p>
<%= f.label :range %> <br>
<%= f.select :range, ['land', 'sea', 'sky', 'underground'], :prompt => 'Select One' %>
</p>
<p>
<%= f.submit %>
<p>
<% end %>
When I try to enter in a new animal, here is what I get:
<ActionController::Parameters {"name"=>"cat", "scientific_name"=>"Felis catus", "range"=>"land"} permitted: false>
I'm wondering why I keep getting "permitted:false" when I have code in animals_controller.rb that states that these params are permitted! Can anyone point out anything or give me some suggestions?
Your params should look like
<ActionController::Parameters {"animal" => {"name"=>"cat", "scientific_name"=>"Felis catus", "range"=>"land"} } permitted: false>
Also, in the form, can you change :animal to #animal.
Alternatively, you can try this
params.require(:animal).permit(:name, :scientific_name, :range).permitted?
Problem is with this line render plain: params[:animal].inspect
because you are printing/accessing params directly without permission instead use :animal_params
render plain: animal_params.inspect
this lines #animal = Animal.new(animal_params) is fine. I guess your creating process works perfectly only.

Ransack search include parameter

I'm using gem 'ransack' to search records.
The page I'm programming starts with ONLY a dropdown to select #department.
After that, I want Ransack to search within #department.
I need to include an additional parameter department=2 with the Ransack search parameters. (It works if I insert that into the browser URL).
Browser URL after I type in department=2
http://localhost:5000/departments/costfuture?department=2&utf8=%E2%9C%93&q%5Bid_eq%5D=&q%5Bproject_year_eq%5D=&q%5Boriginal_year_eq%5D=&q%5Bclient_id_eq%5D=43&q%5Blocation_name_cont%5D=&q%5Bproject_name_cont%5D=&q%5Bcoststatus_id_in%5D%5B%5D=&q%5Bcoststatus_id_not_in%5D%5B%5D=&q%5Brebudget_true%5D=0&q%5Bnew_true%5D=0&q%5Bconstruction_true%5D=0&q%5Bmaintenance_true%5D=0&commit=Search
This is the controller:
def costfuture
#departments = current_user.contact.departments
if params[:department]
#department = Department.find(params[:department])
#search = #department.costprojects.future.search(params[:q])
#costprojects = #search.result.order(:department_priority)
end
respond_to do |format|
format.html # index.html.erb
format.json { render json: #departments }
end
end
I tried this in the view:
<%= search_form_for #search, url: departments_costfuture_path(:department => #department.id) do |f| %>
But, the resulting URL is missing the department=2.
If you want to pass the department option through to Ransack, you can do this with a hidden field within your search_form_for:
<%= search_form_for #search, url: departments_costfuture_path do |f| %>
<%= f.hidden_field :department_eq, value: #department.id %>
<%# Other form code here %>
<% end %>
But if you want to search a particular department, then it's better to use Rails routes for that. You can generate URLs like /departments/2/costfuture by modifying config/routes.rb:
resources :departments do
get 'costfutures', on: :member
end
Now you can use the resulting URL helper to generate links that will set params[:id], and you can use that to retrieve #department.
I ended up using hidden_field_tag inside search_form_for.
<%= search_form_for #search, url: departments_costfuture_path do |f| %>
<%= hidden_field_tag :department, #department.id %>
<%= f.search_field :last_name_or_first_name_cont %>
<% end %>
Then params[:department] and params[:search] will be accessible in the controller.

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.

Rails search form submit to show method

I am trying to set up a form in a Rails view to submit an id back to the show method in the controller. My form uses autocomplete to set the hidden id field:
<%= form_tag students_path, id: 'search_student_name', method: :get do %>
<%= text_field_tag :search_name, '', size: 30 %>
<%= hidden_field_tag :id %>
<%= submit_tag "Search", name: nil %>
<% end %>
I'm using the standard controller 'show' method generated by the scaffold:
# GET /students/1
# GET /students/1.json
def show
#student = student_scope.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #student }
end
end
I'd be grateful for any advice on the combination of form url / post method / additional routes to get this to work. Is this the way you'd normally do this is Rails, or should I set up a new controller method to handle the submitted form?
Thanks in advance
Because it is not exactly a Restful show, you should create a new action, search.
#routes.rb
post 'search' => 'students#search'
#student_controller.rb
def search
#student = Student.find_by_name params[:search_name]
render action: 'show'
end
The form doesn't need to send the :id as far as I can tell.
<%= form_tag search_path, method: :get do %>
<%= input_tag :search_name, type: 'text' %>
<%= submit_tag "Search" %>
<% end %>

Resources