Params to controller - ruby-on-rails

In my project I got a view, in this view I have a date input like this:
<%= form_tag installations_path, :method => :csv, :class => 'form-search' do %>
<%= select_date(date = Date.current, options = {}, html_options = {}) %>
<%= submit_tag "Save" %>
<% end %>
In my controller Installation I got a method with the name "csv" this method generate a Csv. Example:
def csv
#consumption = current_user.get_consumptions(params[:year])
respond_to do |format|
format.html
format.csv { send_data #consumption.to_csv }
end
end
When I execute the view I receive this error:
param is missing or the value is empty: installation
The problem is that in my installations_params I have require(:installation) cause I use object installation in others methods.
def installation_params
params.require(:installation).permit(:year,...)
end
What is the best way to resolve this problem ?

The request log may help you firstly.
If you generate the csv as a GET request, then change the code
from:
<%= form_tag installations_path, :method => :csv, :class => 'form-search' do %>
to:
<%= form_tag csv_installations_path, :method => :get, :class => 'form-search' do %>
Make sure the csv_installations_path is exist.
Then, you can get the year params as params[:year] if your input named year.
At last, You don't use any install_params in csv method
Hope it helps you.

Related

rails - multiple paths for a search form

I'm implementing the website. I got a problem for a search form. I upload my code, and what i want to ask is how to set the search 'path' through 'index' and 'historical' on homes_controller
Below, my code:
app/controllers/homes_controller
def index
#homes = Home.where(:category => 1).reverse
end
def historical
#homes = Home.where(:category => 2).reverse
end
app/views/layouts/application.html.erb
Below, this code is temporary code for now. I should change it.
<%= form_tag(homes_path, :method => 'get', id: "search-form" do %>
<%= text_field_tag :search, params[:search], placeholder: "검색" %>
<%= submit_tag "검색", :name => nil %>
<% end %>
Am not sure what you are supposed to do here
But as per the question - I can give a solution to your problem
Keep an instance variable in your controller actions - like this
app/controllers/homes_controller
def index
#homes = Home.where(:category => 1).reverse
#search_path = "path you want to give"
end
def historical
#homes = Home.where(:category => 2).reverse
#search_path = "path you want to give"
end
and in your layout you can use it like this
app/views/layouts/application.html.erb
<%= #search_path.present? %>
<%= form_tag(#search_path, :method => 'get', id: "search-form" do %>
<%= text_field_tag :search, params[:search], placeholder: "검색" %>
<%= submit_tag "검색", :name => nil %>
<% end %>
<% end %>

How do I validate text_field_tag used for searching purpose in rails 4.1

In homepage/index:
<%= form_tag :controller => 'hotels', :method => 'get' do %>
<%= text_field_tag :search, nil, :class => 'search-box'%>
<%= submit_tag "Search", :name=>'btnsearch' %>
<%end%>
In hotels_controller:
def index
#hotels= Hotel.where('hotel_location LIKE ?',"%#{params[:search]}%")
I am new to Rails and I am wondering that how to validate text_field_tag for nil value.Means if no record was found, then display the error message without redirecting to the hotel/index page.
Your question is somewhat paradoxial:
If no record was found, then display the error message without
redirecting to the hotel/index page
What you're asking is to perform the functionality which can only be achieved after you've sent a request to your app, and then display the message without redirecting?
Ajax
You'll probably be best using Ajax (Asynchronous Javascript and XML):
This is a way of sending & receiving requests outside the scope of the typical "HTTP" request (IE without reloading the page). This sounds like what you're looking for, as it will ensure you're able to return the data you want without redirecting to your index view again.
The importance of Ajax is that it provides many HTTP developers with the ability to create much more "organic" interaction structures within their applications (IE not having to reload the page every time you want to do something)
Ajax is very simple to implement - I'd recommend it for you:
--
Search
Here's what I'd do:
#app/assets/javascripts/application.js
$(document).on("ajax:success", "#search", function(status, data, xhr){
$(this).append(data);
});
#config/routes.rb
...
resources :hotels do
get :search, on: :collection
end
#app/views/homepage/index.html.erb
<%= form_tag hotels_search_path, method: :get, id: "search", remote: true do %>
<%= text_field_tag :search, nil, :class => 'search-box'%>
<%= submit_tag "Search", :name=>'btnsearch' %>
<% end %>
This will send a "get" request to your hotels_search path - which will allow you to do the following:
#app/models/hotel.rb
class Hotel < ActiveRecord::Base
def self.search search
results = where('hotel_location LIKE ?',"%#{search}%") if search
if results
return results
else
return "No Records"
end
end
end
#app/controllers/hotels_controller.rb
class HotelsController < ApplicationController
respond_to :js, :json, :html
def search
#hotels = Hotel.search params[:search]
respond_with #hotels, layout: false
end
end
how to validate text_field_tag for nil. if no record was found, then display the error message without redirecting to the hotel/index page.
Looks like you need to validate it on client side. You can checkout bootstrap validator which is really nice for using validations on client side.
If you want to write your own js to handle it then you can do something like this:
$(document).on("click","#your_btn_id",function(e){
var textValue = $(this).closest(".search-box").val();
if(textValue == ""){
e.preventDefault();
alert("Please enter some value");
}
});
Update:
You can also utilize HTML5 validations and won't need any js
<%= form_tag :controller => 'hotels', :method => 'get', :validate=>true do %>
<%= text_field_tag :search, nil, :class => 'search-box', :required => true %>
<%= submit_tag "Search", :name=>'btnsearch' %>
<%end%>
If you don't want to use ajax then you can do:
def index
#hotels= Hotel.where('hotel_location LIKE ?',"%#{params[:search]}%")
if #hotels
#your action
else
flash[:notice] = "Please enter a valid value"
render 'your_form_action'
end
end
Since Rails generates HTML5, I am sure you can leverage its required attribute to have Search text box as a mandatory field on your view page. Like this:
<%= form_tag :controller => 'hotels', :method => 'get' do %>
<%= text_field_tag :search, nil, :class => 'search-box', :required => true %>
<%= submit_tag "Search", :name=>'btnsearch' %>
<%end%>
Just to be assured that your controller doesn't get nil in params[:search], you can change controller's index action with:
before_filter :validate_search, :only => [:index]
def index
#hotels = Hotel.where('hotel_location LIKE ?',"%#{params[:search]}%")
if #hotels.present?
# other operation here!
else
redirect_to :back # will work only when referrer is present!
rescue ActionController::RedirectBackError
redirect_to root_path
end
end
def validate_search
if params[:search].nil?
redirect_to root_path, notice: 'Enter few characters to search!'
end
end

delete is not working, instead it is inserting a new empty record

I've tried a lot to delete a record from my DB, but I have failed. Instead of deleting the selected value it is inserting a new empty record into my db. Please help me out.
My Controller is:
class CatvaluesController < ApplicationController
...
def destroy
#catvalue = Catvalue.find(params[:id])
#catvalue.destroy
redirect_to catvalues_path
end
....
end
and my form is:
<%= form_for(#catvalue) do |f| %>
<%= f.collection_select :id, #catvalues, :id, :v_name, {}, class: 'drop-down'%>
<%= f.submit 'Destroy', :confirm => 'Are you sure you want to destroy your account?' %>
<% end %>
form_for by default takes post method
<%= form_for #catvalue, :method => :delete do |f| %>
Okay, so I'm now adding url to the form helper, try this one!
<%= form_for #catvalue, :url => "/catvalues/#{#catvalue.id}",:method => :delete do |f| %>
You are submitting a POST request, it will call the create action on your controller hence your empty model.
You have to use the delete http method to call the destroy action on your controller :
<%= form_for(#catvalue, :method => :delete) do |f| %>

update_attributes with none-standard form

I have cobbled together a form due to some oddities in my code and routes. Things work for adding data to the database, but I can't quite seem to figure out how to update data. Here is some code.
new.html.erb
<% form_tag '/list' do %>
Episodes Completed:
<%= text_field_tag "completed" %>
Watch Status
<%= collection_select(nil, 'id', #show_status, :id, :state) %>
<%= hidden_field_tag('show_id', #show.id) %>
<%= submit_tag 'Add' %>
<% end %>
edit.html.erb
<% form_tag("/list/#{#show_completion.show.id}", :method => :put ) do %>
Episodes Completed:
<%= text_field_tag "completed", #show_completion.episodes_completed %>
Watch Status
<%= collection_select(nil, 'id', #show_status, :id, :state) %>
<%= hidden_field_tag('show_id', #show_completion.show.id) %>
<%= submit_tag 'Edit' %>
<% end %>
Here is the controller's Create and Update methods
def create
#show_completetion = ShowCompletionStatus.new
#show_completetion.user_id = current_user.id
#show_completetion.episodes_completed = params[:completed]
#show_completetion.status_state_id = params[:id]
#show_completetion.show_id = params[:show_id]
#show_completetion.save
end
def update
#show_completion = ShowCompletionStatus.find(params[:id])
#show_completion.episodes_completed = params[:completed]
#show_completion.status_state_id = params[:id]
#show_completion.show_id = params[:show_id]
if #show_completion.update_attribute('episodes_completed', params[:completed])
redirect_to "/list/#{current_user.username}"
else
redirect_to "/list/#{params[:id]}/edit"
end
end
Here are my routes for these:
match "list/" => "list#create", :via => :post
match "list/new/:show_id" => "list#new", :constraints => { :show_id => /[0-9]+/ }
match "list/:id/edit" => "list#edit", :constraints => { :id => /[0-9]+/ }, :via => :get
match "list/:id" => "list#update", :constraints => { :id => /[0-9]+/ }, :via => :put
I have been trying different things to get this to work for the better part of 4 hours now. I think I am just missing something, but I just can't see it.
Is there a better way to do the form that makes it work better?
Any help is appreciated.
I solved this issue by making a hash and passing it to the update attributes with the key value pairs of what the objects attributes would be. Since updates_attributes takes a hash and not an object it was a simple solution once the connection was made.
Try to replace your update_attribute call for a save call.
Also, if you're writing everything from scratch instead of using the builtins, try to use save! instead of save: it will raise an exception if it fails, unlike the plain save that just returns false.

Ruby on Rails: Why a select box does not show the current object value?

Here is the relevant code from views/products/edit.html.erb:
<%= form_for(:product, :url => {:action => 'update', :id => #product.id}) do |f| %>
<%= render(:partial => "form", :locals => {:f => f}) %>
<%= submit_tag("Update Product") %>
<% end %>
from views/products/_form.html.erb:
<%= select_with_new_option(f, :shop, :name, :id) %>
and from helpers/products_helper.rb:
def select_options_with_create_new(objects, text_field, value_field, options={})
object = objects.to_s.singularize
all_objects = object.capitalize.constantize.all
all_objects = all_objects.sort_by(&options[:order_by]) if options.has_key?(:order_by)
select_options = all_objects.map{ |obj| [obj.send(text_field), obj.send(value_field)] }
select_options << [wrap_create_new_option("create new #{object}".titleize), "new_#{object}"]
options_for_select(select_options)
end
def wrap_create_new_option(str)
">> #{str} <<"
end
# By default, sorts by 'text_field'.
def select_with_new_option(f, object, text_field, value_field)
f.select(:"#{object}_id", select_options_with_create_new(object.pluralize, text_field, value_field, :order_by => text_field))
end
I expect the select box to be #product.shop_id by default, but this is not true (the first option is always the default value).
What am I missing ?
Alright, I got it. Just remove options_for_select(select_options) in the select_options_with_create_new method.
The options_for_select assembles the 2-d array select_options into a string of html options, which is accepted by the select form helper, however, without assigning the selected attribute. Just pass the 2-d array to the select method as the second argument, it would assign the selected automatically.
I think that, in this case, all you need to do is make sure you set #product in your edit action:
def edit
#product = Product.find(params[:id])
end
Then change your first line:
<%= form_for(:product, :url => {:action => 'update', :id => #product.id}) do |f| %>
to
<%= form_for(#product, :url => {:action => 'update', :id => #product.id}) do |f| %>
The first code block will certainly update the proper product, but you'll only see the current values reflected if you generate a form_for #product, with that #product variable set.

Resources