Ruby Hash is including extra values for a single key - ruby-on-rails

I've tried to build a hash multiple ways, but when I use it in a grouped_options_for_select tag, there are extra values that aren't in my original hash. Here are two ways I've tried to build my hash:
UNITS_OF_MEASURE_GROUPED = {
"Dry" => ["oz", "lb", "g", "kg"],
"Liquid" => ["floz", "gal", "ml", "L"],
"Other" => ["each"]
}.freeze
and a bit more explicit and very wordy:
UNITS_OF_MEASURE_GROUPED = {}
UNITS_OF_MEASURE_GROUPED[:dry] = ["oz", "lb", "g", "kg"]
UNITS_OF_MEASURE_GROUPED[:liquid] = ["floz", "gal", "ml", "L"]
UNITS_OF_MEASURE_GROUPED[:other] = ["each"]
UNITS_OF_MEASURE_GROUPED.freeze
But the grouped_options_for_select always includes "floz" and "each" in the first section ("dry"). Please see attached image.
I forgot to add my form element code:
<%= form.select :unit_of_measure, grouped_options_for_select(UNITS_OF_MEASURE_GROUPED) %>
As per Guiseppe in another comment, I tried <%= form.select :unit_of_measure, UNITS_OF_MEASURE_GROUPED %> with the same result.
Something that does seem really weird is when I go into the console after triggering an error, my UNITS_OF_MEASURE_GROUPED hash shows this:
{:dry=>["oz", "lb", "g", "kg", ["floz", "gal", "ml", "L"], ["each"]], :liquid=>["floz", "gal", "ml", "L"], :other=>["each"]}
My guess is that's screwing up the HTML and getting confused. Does that help?
What am I missing? Thank you SO much in advance.

I'd be inclined to concur with the suspicion that something mangling your hash is to blame. To find out what, try a deeper freeze:
UNITS_OF_MEASURE_GROUPED = {
dry: %w(oz lb g kg),
liquid: %w(floz gal ml L),
other: %w(each)
}.transform_values(&:freeze).freeze
This'll (hopefully) throw a FrozenError, and accompanying illuminating stack trace, from wherever deep in the app/framework is screwing with it.

The problem is the way you are calling form.select inside the erb tag.
You are supposed to pass a collection but instead, you are passing a string as the second argument.
You should pass UNITS_OF_MEASURE_GROUPED instead of grouped_options_for_select(UNITS_OF_MEASURE_GROUPED) as in the following example:
<%= form.select :unit_of_measure, UNITS_OF_MEASURE_GROUPED %>.
If you look at rails guides you can find an example.
The select helper
Wraps ActionView::Helpers::FormOptionsHelper#select for form builders:
ActionView::Helpers::FormOptionsHelper#select requires a collection as parameter.
Edited.
It could be the generetion of hidden fileds that you get by default
Try the following
<%= form.select :unit_of_measure, UNITS_OF_MEASURE_GROUPED, {include_hidden: false} %>
See Documentation for details.

Related

having trouble understanding :multiple => true in a checkbox

I am very new to Ruby on Rails, I have inherited control of a Ruby/Rails web based database(created by another) for generating and tracking engineering functions. I use Aptana IDE.
My issue is that I am trying to use a form helper to select multiple values for our "product lines". I use 10 check boxes, and I get the correct output of one value if I don't use ":multiple => true".
See output image:
works as intended
<%= f.check_box :product_line, {:class => "field"}, "A9", false %> A9
(10 times with different values where "A9" is, so there are ten checkbox's total, image shows "A7" check box returned)
By simply adding the :multiple => true, the output changes as seen in the image below:
see output image:
returns too much
<%= f.check_box :product_line, {:class => "field", :multiple => true}, "A9", false %> A9
Why are all of those "-" added before the output only if the multiple selection is made? I want it to return only comma separated values of the checkbox, i.e. " A9, A7"
PRODUCT_LINES = [ "A9", "A7", "AG", "AF", "S3", "Legacy", "K/Kpro", "EMW", "HD", "Non-Metallic" ]
other ideas:
Can I loop through an array of :product_line to get what im looking for instead?
I was also playing with the multiple selection in a drop down menu but could never select a second option before the drop down returned and only selected my first selection.
Why are all of those "-" added before the output only if multiple
selection is made?
From the docs (read the Gotcha) when multiple is set to true all selections will be stored in an array of product_lines but un-selected check_boxes will also be reserve as an empty strings in the sent pararms so for the result you are seeing product_lines would be something like:
product_lines = ["", "", "", "A9", "A7"]
Can I loop through an array of :product_line to get what im looking
for instead?
Well, actually this takes us right to the problem in using multiple: true in your code.
The process explained in (1) above is how the check_box_tag was designed, the problem you are seeing is in presentation probably in your ECN#show. Without reviewing code there i am only guessing but usually it's something like:
<%= #ecn.product_lines.join('-') %>
which should be
<%= #ecn.product_lines.reject(&:blank?).join(',') %>
where: reject(&:blank?) to get rid of empty strings then joining with commas as you need
Hope this helps!

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.

haml select_tag with constants

I'm new to Ruby and Haml, so I"m going around in circles on this. Googling isn't giving me any sample code I can use.
I can use the select_tag and populate the list from a table. But I can't figure out how to use a simple static list of items. Can someone change this to be proper Haml? Note: the source table is 'email' and the field is 'status'.
= select_tag(:email, :status, {"canceled", "pending", "success"})
I'm looking to get a dropdown list that just has the items "canceled, pending, success" in it.
The error I get is odd number list for Hash._hamlout.format_script...
Update: I found some sample code that seemed to be what I need, and it doesn't give any errors, but the dropdown box is empty:
= select_tag(:email, :status,{ "canceled" => "1", "pending" => "2", "success"=>"3"})
Here is the HTML it produces:
<select female="2" male="1" id="email" name="email">status </select >
You are using the tag helper rather than the object-oriented helper. Use select
I'd also recommend using options_for_select. Like so:
= select(:email, :status, options_for_select([["canceled", "1"], ["pending", "2"], ["success", "3"]]))
See:
http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/select
http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/options_for_select
Got it working! I need to use "Select" instead of "Select_tag". :-)
= select(:email, :status,{ "canceled" => "canceled", "pending" => "pending", "success"=>"success"})

Rails form formatting

I've just had Submitting multiple forms in Rails answered which led to another problem. In my form I have the following (there's quite a bit more):
= hidden_field_tag :event_id, :value => #event.id
.control-group
= label_tag :title
.controls
= select(:registration, "registrations[][title]", Registration::TITLE)
and the last line returns:
"registrations"=>[{"title"=>{"registration"=>"Mr"},
as opposed to the expected:
"title"=>"Mr"
I've tried:
= select(:registration, "registrations[][title]", Registration::TITLE)
which returns:
undefined method `registrations[][title]' for #
and also tried:
= select("registrations[][title]", Registration::TITLE)
which returns:
wrong number of arguments (2 for 3)
Look at the parameters below, event(_id) is only there once then the :title oddness starts, any idea what the problem may be?
{"utf8"=>"✓",
"authenticity_token"=>"BQXm5fngW27z/3Wxy9qEzu6D8/g9YQIfBL+mFKVplgE=",
"event_id"=>"7",
"registrations"=>[{"title"=>{"registration"=>"Mr"},
"first_name"=>"Name1",
"last_name"=>"Surname1",
"company_name"=>"Company1",
"designation"=>"Designation1",
"landline"=>"Landline1",
"cell"=>"Cell1",
"email"=>"address1#example.com",
"member"=>{"registration"=>"No"},
"dietary"=>{"registration"=>"None"},
"specify"=>"None"},
{"first_name"=>"Name2",
"last_name"=>"Surname2",
"company_name"=>"Company2",
"designation"=>"Designation2",
"landline"=>"Landline2",
"cell"=>"Cell2",
"email"=>"address2#example.com",
"member"=>{"registration"=>"No"},
"dietary"=>{"registration"=>"None"},
"specify"=>"None",
"title"=>{"registration"=>"Mr"}},
{"first_name"=>"Name3",
"last_name"=>"Surname3",
"company_name"=>"Company3",
"designation"=>"Designation3",
"landline"=>"Landline3",
"cell"=>"Cell3",
"email"=>"address3#example.com",
"member"=>{"registration"=>"No"},
"dietary"=>{"registration"=>"None"},
"specify"=>"None"}],
"commit"=>"Submit registrations"}
Please not that :dietary and :member are formated in the same way as :title. Thanks in advance for your assistance!
EDIT
So submitting to the hash via a text_field_tag is a simple is:
= text_field_tag "registrations[][first_name]"
But the problem comes in with my hidden_field_tag and select_tag.
It's adding bad values, for example:
"title"=>{"registrations"=>"Mr"}
and basically it seems I need to find a better way to add those values into the hash. I'll continue trying to find a solution and will post it here unless someone beats me to it.
Unless i'm reading it wrong, your first two select calls are the same. Have you tried = select(:registrations, "title", Registration::TITLE)? If you look at the documentation of the method in api.rubyonrails.org, it will state that the first value is the object, second is the property. That would be registrations => { :title => "Value" }, in the parameters. If you just want :title => "Value", then you need the select_tag method.

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.

Resources