get selected items from select_tag - ruby-on-rails

I have this line in my rails app:
<%= select_tag :questionnaire_id,
options_for_select(#questionnaires_types, #questionnaires_ids),
:multiple => true, :size => 7 %>
which works fine.
but when I try to use the multiple values that were selected I get this:
questionnaire_id"=>["1687,1688,1689,1690,1691,1724"]
instead of this:
questionnaire_id"=>["1687", "1688", "1689" ,"1690", "1691", "1724"]
i.e. I get 1 item instead of 6 items.
any suggestions?

According to rails code: https://github.com/rails/rails/blob/41231ef6c6c6a6e546b69add28f04aafb9e0e952/actionview/lib/action_view/helpers/form_tag_helper.rb#L134
The name must end with [] to be make sure you receive an array.
def select_tag(name, option_tags = nil, options = {})
option_tags ||= ""
html_name = (options[:multiple] == true && !name.to_s.ends_with?("[]")) ? "#{name}[]" : name
if options.delete(:include_blank)
option_tags = content_tag(:option, '', :value => '').safe_concat(option_tags)
end
if prompt = options.delete(:prompt)
option_tags = content_tag(:option, prompt, :value => '').safe_concat(option_tags)
end
content_tag :select, option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
end
So just change it to questionnaire_ids[]
Hope that helps.

I think a collection_select would look nice but I cannot help with that since you did not post anything about the model. Maybe try this so that it knows it is a collection:
<%= select_tag "questionnaire_ids[]", options_for_select(#questionnaires_types, #questionnaires_ids), :multiple => true, :size => 7 %>
Or you could just parse the string you currently receive using #split.
Otherwise post a bit more code about the associations between Questionnaire and what ever this model is.

Well, just in case that someone will come to this issue, I found the problem.
It seems to be a bug in rails.
I was using remote_form_for, and that gave me the strange behaviour. I tried to change the form to form_for instead, and I got an array with 6 items.
Rails, Rails, when will you be like .Net? :-(

Related

NoMethodError when returning an array in a form

I'm building an app for a restaurant and I have a form where I add meals to an order and a price field gets dynamically updated depending on what dishes and how many of them you pick.
To do that I built a nested form (I think that doesn't matter anyway) which looks as follows:
.nested-fields
= f.collection_select(0, #dishes.collect{ |dish| [dish.name, :data => {:description => dish.price}]}, :name, :name, {include_blank: true}, {class: "meal-select"})
= f.select :quantity, options_for_select((1..10))
= f.text_field(:price, disabled: true)
= link_to_remove_association "X", f
The thing that bugs me is the collection_select. As you can see, I am returning an array with a name and a data-description which goes to the HTML tag. Based on the data-description, my price field gets updated.
However, I have no idea what method I should choose to extract the name of a dish. As you can see I tried 0 since name of the dish is always first in the array. I have also tried :first, :name but none of those works! The error I get is:
"NoMethodError in Orders#new
undefined method '0' for #Meal:0x007fe4eb8e26c8"
or when I use :name
undefined method `name' for ["Zupa z Krewetkami", {:data=>
{:description=>17.0}}]:Array
Naturally, it points to:
= f.collection_select(0, #dishes.collect{ |dish| [dish.name, :data => {:description => dish.price}]}, :name, :name, {include_blank: true}, {class: "meal-select"})
I don't think the problem lies in my controller but, I'll show it just in case:
def new
#dishes = Dish.all
#order = current_user.orders.build
end
I tried looking for an answer here but as you can see the problem has not been solved and it was slightly different than mine.
To sum up - my question is what method I should use to extract name of the dish from my array in collection_select. Thanks!
Here is how you can use collection_select
...
= f.collection_select :meal_select, #dishes, :name, :price, {include_blank: true}, {class: "meal-select"}
...
For more details see the docs.
Use below approach
options_for_select( [['First', 1, {:'data-price' => 20}],
['Second', 2, {:'data-price' => 30}]] )
= f.select :meal_select, options_for_select(#dishes.collect{ |dish| [dish.name, dish.price,{'data-description' => dish.price}]}), :class => 'meal-select'

Ruby on Rails - How to use a select box to change an attribute of the selected items?

I'll start off with a bit of context to my question. I have a group of offices which each have reviewers associated with them. A reviewer can only be associated with one office. I want to create two select boxes. One lists all of the reviewers that are associated with the office I am viewing, the other lists all of the reviewers that are available (which is basically all of the reviewers that aren't already assigned to this office).
The goal of the current reviewer's listbox is to set their office to nil when they are selected. The goal of the available reviewers listbox is to set their office to this office's id when they are selected. I'm not sure how to change only the reviewers' office_id when using a select box.
Code-wise, what I have so far is this:
office_controller.rb
def edit
#office = Group.find params[:id] if params[:id]
#current_reviewers = Reviewer.find_all_by_group_id(#office.id)
#available_reviewers = Reviewer.where('group_id <> ?',[#office.id])
end
def update
?
end
office/edit.html.erb
<% form_for(#office, :url => {:controller => :office, :action => :update, :id => #office.id}, :html => {}) do |f| %>
...
<%= select_tag 'removedReviewers', options_from_collection_for_select(#current_reviewers, "id", "display_name"), :multiple => true %>
<%= select_tag 'chosenReviewers', options_from_collection_for_select(#available_reviewers, "id", "display_name"), :multiple => true %>
...
<% end %>
Any suggestions would be greatly appreciated. Thanks!
I solved this by adding the ability to get a select_tag to get the selected objects as a collection via the [] modifier of the select_tag name. So, in this example it was:
<%= select_tag 'removedReviewers[]', options_from_collection_for_select(#current_reviewers, "id", "display_name"), :multiple => true %>
And for the controller code to handle it, I did this:
#removedReviewers = params[:removedReviewers]
if !#removedReviewers.nil?
#removedReviewers.each do |reviewer|
#reviewer = Reviewer.find(reviewer)
#reviewer.group_id = nil
#reviewer.save
end
end
And the equivalent for the chosen/available reviewers.

How do I search for multiple records in a search form?

I am trying to allow the user to be able to choose multiple records in a field on the search form.
Something like this:
<%= f.input_field :neighborhood_id, collection: Neighborhood.order(:name), :url => autocomplete_neighborhood_name_searches_path, :as => :autocomplete, 'data-delimiter' => ',', :multiple => true, :class => "span8" %>
It sends it to my search model like this: #search = Search.create!(params[:search])
This is what the Search.rb model does with it:
key = "%#{keywords}%"
listings = Listing.order(:headline)
listings = listings.includes(:neighborhood).where("listings.headline like ? or neighborhoods.name like ?", key, key) if keywords.present?
listings = listings.where(neighborhood_id: neighborhood_id) if neighborhood_id.present?
listings
The issue is that this is just accepting 1 neighborhood_id, so I am getting this error when I choose multiple objects:
undefined method `to_i' for ["Alley Park, Madison"]:Array
Where Alley Park and Madison are the names of 2 neighborhoods, not the IDs.
So how do I get this working?
Thanks.
Edit 1
The issue seems to not be in the lookup of the params[:search] per se, but rather in the conversion of the form input to an array of entries. I tried changing the search method to be something like:
listings = listings.includes(:neighborhood).where("neighborhoods.name like ?", neighborhood_id) if neighborhood_id.present?
Don't get hung up on the fact that I am looking up neighborhood.name and passing in neighborhood_id. I just did that because I know that the params for the field neighborhood_id were actually the names of the neighborhood. If this had worked, I would have refactored some stuff, but it didn't. So don't get hung up on that.
But that still returns the error undefined method 'to_i'....
Also, I still get that error even if I just pass in 1 option.
listings = listings.where("neighborhood_id in (?) ", neighborhood_id)
You can get the id instead of neighborhood names from the input field like this:
<%= f.input_field :neighborhood_id, collection: Neighborhood.order(:name), :url => autocomplete_neighborhood_name_searches_path, :as => :autocomplete, 'data-delimiter' => ',', :multiple => true, :class => "span8", :input_html => { :id => "neighborhood_id" } %>

Rails Multiple Select boxes: Injecting default values from params

I currently have a multiple select box in a rails form that looks like this:
= select_tag :in_all_tags, options_from_collection_for_select(Tag.where(:project_id => #project.id), :id, :name, #in_all_tags_param), { :id => "tags", :tabindex => "3", "data-placeholder" => "Choose Tags", :multiple => "multiple" }
Where
#in_all_tags_param = params[:in_all_tags]
The problem is, #in_all_tags_param will only populate the select form with the last value from params[:in_all_tags]. So, if the url string reads in_all_tags=5&in_all_tags=8, the pre-selected value in the multiple select will only be 8.
From what I understand, the way around this is to append [] to the field name for multiple params, so that :in_all_tags becomes in_all_tags[]
BUT, when I try this, submitting the form returns:
Expected type :default in params[:in_all_tags], got Array
Any suggestions appreciated.
Cheers...
You need to add a :name element to the same hash with :multiple => true in it. So I use something similar for Genres on an app for mine and I do { :multiple => true, :name => "lesson[genre_ids][]" }. The name has to be model[attribute][].

Not setting anything in Rails' collection_select

I have a Rails 2.3 web application that uses the collection_select helper with :multiple => true to handle a habtm relationship. This is working fine to set one or multiple values, however I have not figured out how to allow to REMOVE all selections.
Code:
<%= f.collection_select :category_ids, Category.find(:all), :id, :name,
{ :selected => #entry.category_ids },
{ :multiple => true, :name => 'entry[category_ids][]' }
%>
Once the user has ever set a category for an entry, how would I go about allowing it to be removed, so that this entry has no category? Is this possible with collection_select or would I need to add a checkbox to handle this specially?
P.S: I already tried with :prompt, :include_blank and :allow_blank, but as far as I could see neither of them did anything.
In your controller's update action, put in the following line:
params[:entry][:category_ids] ||= []
before the call to Entry.find.

Resources