Rails form using GET request: How to remove button and utf8 params? - ruby-on-rails

I'm just trying to create a simple select menu that takes you to a specific URL. So far I have something like this:
# haml
= form_tag new_something_path, method: :get do
= select_tag :type, options_for_select(my_array)
= submit_tag 'New Something'
However, when I submit the form I get the UTF8 parameter as well as a "commit" parameter with the text of the button.
How can I remove the UTF8 and commit parameters?

Removing the commit param is relatively simple, you need to specify that the input does not have a name:
submit_tag 'New Something', name: nil
Regarding the UTF-8 param...it serves an important purpose. Once you understand the purpose of the Rails UTF-8 param, and for some reason you still need to remove it, the solution is easier than you think...just don't use the form_tag helper:
# haml
%form{action: new_something_path, method: 'get'}
= select_tag :type, options_for_select(my_array)
= submit_tag 'New Something', name: nil

You can get rid of the utf8 param by adding the enforce_utf8: false option of form_tag (and also form_form) like the following:
= form_tag new_something_path, method: :get, enforce_utf8: false do
(thanks to #Dmitry for pointing that out)
But please make sure you don't need it: What is the _snowman param in Ruby on Rails 3 forms for? (I'm not sure if it is actually relevant for GET forms.)
The additional parameter is generated by the submit button can be removed by setting the name: false option on your submit_tag (Also works for submit in case of form_for).
= submit_tag 'New Something', name: nil

Related

Rails - Merge Multi-Select Params into comma-separated string

I have a select box that allows multiple values, to filter the results on the page. When I select multiple, the Parameters that are submitted look like this:
Parameters: {"categories"=>["books", "films"], "commit"=>"Submit", "id"=>"87"}
When I am returned to the page, the URL is:
http://localhost:3000/87/projects?categories%5B%5D=books&categories%5B%5D=films&commit=Submit
The URL I would like to return is:
http://localhost:3000/87/projects?categories=books,films
How can I return these params[:categories] as a comma-separated string in the URL? Also, is it possible to remove the "&commit=Submit" from the URL?
Here is my full form code:
<%= form_with url: project_path(#project), local: true, method: :get, skip_enforcing_utf8: true do |form| %>
<%= form.select(:categories, #categories.map {|category| [category.name,category.slug]}, options = { selected: params[:categories], include_blank: "Select Categories", include_hidden: false }, html_options = { multiple: true }) %>
<%= form.submit 'Submit' %>
There's a couple JS & Rails way to do what you want. I can think of a quick and easy one using rails only: Redirecting the URL you are getting to another route with the data parsed as you want it. Like this -->
Assuming this is your route to project_path : get 'project', to: 'project#reroute', as: :project
You can go to your reroute method in the project controller and parse the data you got.
project_controller.rb
class ProjectController < ApplicationController
def reroute
redirect_to your_path(categories: params[:categories].join(','))
end
end
This converts your categories array to a string with your values separated by commas. It is not an array anymore. and it also removes "&commit=Submit" like you wanted.
If you dislike the rails routing method, you can also make your submit button to run some JS functions that builds the url string as you want it. For example <%= submit_tag , :onclick => "return buildUrl();" %>
Having this said, I must say I agree with Edward's comment, the url encoded format is standard and works out of the box, no need for all the additional rerouting and parsing. Im pretty sure whatever you need the data for can be used with the URL encoded format with proper parsing.

Cannot pass parameters to controller

I have the following haml code in index.haml
%h1.content-header{id: 'content-header'} HEADER
%section.form
%form.standard{action: some_path, method: 'get'}
%fieldset.search{'aria-labelledby' => 'content-header'}
%input{type: 'search', name: 'name', placeholder: 'something', role: 'textbox'} -----(6)
%fieldset.input-actions
%input.primary-action{type: 'submit', value: 'search' , name: 'invokeSearch'}
I have the following in my controller
def index
Rails.logger.debug "#{params[:name]}"
unless #invalid_characters
unless params[:name].blank?
....
....
....
The issue is if i change the name: 'name' in line 6 to say name: 'test' .... params[:test] is always blank in my controller. But if i use name: 'name' , params[:name] seems to work . No clue what i am doing wrong here
If you are using rails you should probably benefit from using one of the form helpers for generating the form. For example forms_for that makes you access things in your model directly. It may look like this.
= forms_for #thing do |f|
= f.text_field :name
= f.text_field :test
= f.submit
In this case there will be a map for the model instance in the params map. Something like
params[:thing][:name]
or
params[:thing][:test]
you can take that map and pass it into a model to create or update it. If you don't want the tight coupling with the model there is the form_tag method that does much the same thing except you need to be more explicit in what value goes where. And fields ends up directly in params instead of in a model hash.
To see how your params come in you can use the inspect method.
puts "params: #{params.inspec}"
or install pry to set a break point with
binding pry
Some ideas. Hope it works out for you. I think you should start with trying to use the rails forms helpers and it will probably sort itself out.

Ruby on Rails: putting class with submit_tag

I was wondering why we have to add a nil when putting :class => "class_name"
<%= submit_tag nil, :class => "class_name" %>
but for this:
<%= f.submit class: "class-Name" %>
I don't need to add the nil
Thanks
<%= submit_tag("Update", :id=>"button", :class=>"Test", :name=>"submit") %>
First parameter is required and it would be value and they any parameter you want to specify, can be done in a hash like :key=>"value".
A look to the way that submit_tag method was implemented clearly answers your question.
def submit_tag(value = "Save changes", options = {})
options = options.stringify_keys
if disable_with = options.delete("disable_with")
options["data-disable-with"] = disable_with
end
if confirm = options.delete("confirm")
options["data-confirm"] = confirm
end
tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options)
end
It takes two arguments, the first is value which by default is "Save changes" and the second is a Hash of options. If you don't pass nil then it will assume that that's the value you want for the input.
Because they are two different methods...
The "submit" method doesn't take a caption because it can infer one from the form that the method is called on, and what object was used to build the form.
The "submit_tag" method is not called on a form object. It is used for more customized form building (more separated from your activerecord model, for example) and so the code can't infer a caption and must get a value as the first argument. All the "formelement_tag" methods (documented here, for example) are like this and can infer less based on your data model.
Obvious answer is that submit_tag and submit are simply different form helper methods that takes different arguments.
The _tag series of methods usually require a name parameter (otherwise they'd be fairly useless tags, so it's always the first argument instead of part of the hash. Because the submit helper is called as part of the form, Rails can assume the field's name property and can then make the options hash the first argument.

Array as Parameter from Rails Select Helper

I'm working on a legacy project that is using acts_as_taggable_on which expects tags to come in arrays. I have a select box allowing users to select a tag on a Course in a field called categories. The only way mass assignment create will work is if params looks like this params = {:course => {:categories => ['Presentation']}}. I've currently a view with this helper:
<%= f.select 'categories', ['Presentation' , 'Round Table' , 'Demo', 'Hands-on'] %>
Which will give me a parameter like params = {:course => {:categories => 'Presentation'}}. This doesn't work since Acts as tag gable apparently can't handle being passed anything other than a collection.
I've tried changing categories to categories[] but then I get this error:
undefined method `categories[]' for #<Course:0x007f9d95c5b810>
Does anyone know the correct way to format my select tag to return an array to the controller? I'm using Rails 3.2.3
I didn't work with acts_as_taggable_on, but maybe this simple hack will be suitable for you? You should put it before mass-assignment.
category = params[:course][:categories]
params[:course][:categories] = [category]
If you are only going to allow the selection of ONE tag, you could do:
<%= f.select 'categories', [['Presentation'] , ['Round Table'] , ['Demo'], ['Hands-on']] %>
Each one item array will have first for the display value, and last for the return value, which in this case will both return the same thing, as the first element of the array is the same as the last element when the array as one element.
Seems like select doesn't give you that option.
If I understand correctly, one option might be to use a select_tag instead and just be explicit about where you want the selection in the params:
<%= select_tag 'course[categories][]', options_for_select(['Presentation' , 'Round Table' , 'Demo', 'Hands-on']) %>
That ought to get your params the way you need them.
Here's what I'm using for one of my projects:
<% options = { include_blank: true } %>
<% html_options = { required: true, name: "#{f.object_name}[#{resource.id}][days][]" } %>
<%= f.select :days, DAYS, options, html_options %>
Without html_options[:name], Rails handles the name of the select tag and spits out something like
service[service_add_ons_attributes][11][days]
but I need
service[service_add_ons_attributes][11][days][]
So I override it.
Hope that helps.

passing large arrays via link_to function (or by other means) in Rails

I know that link_to uses get action by default and also you can change the method to post by passing :method => :post to link_to function, but it does not seem to work. Here is the syntax that I am using:
= link_to "Export" export_path(:data_array => d_array), :method => 'post'
But this does not seem to work. The array is being passed by as a query parameter which I can see in the URL box and it bombs my application since it blows the string length limit in the url string.
Try using form instead:
= form_tag export_path do
- d_array.each do |val|
= hidden_field_tag 'data_array[]', val
= submit_tag 'Export'
Notice that in a controller params[:data_array] will be an array of strings.

Resources