form multiple select - ruby-on-rails

I am learning rails and have been struggling with this for over a day now and can not figure out how to get this to work. I want a select box in my form that can select multiple elements. I have this working with this code:
<div class="field">
<%= f.label :products %><br />
<%= f.select :products, {"A"=>1, "B"=>2, "C"=>3, "D"=>4},{},:size=>5,:multiple=>true %>
</div>
This works fine and produces this HTML:
<div class="field">
<label for="script_products">Products</label><br />
<select id="script_products" multiple="multiple" name="script[products][]" size="5">
<option value="1">A</option>
<option value="2">B</option>
<option value="3">C</option>
<option value="4">D</option></select>
</div>
What I can figure out is how the results get sent/stored. In my view for the "show" action, if I simply print out :products I get this:
Products: --- - '1' - '2' - '3'
If I print out :products.inspect I get this:
Products: "---\n- '1'\n- '2'\n- '3'\n"
and the class is a string. I would think it would be stored as an array, but I can not get it to work. I don't know where the dashes or the newlines come from.

I would consider adding the options as a has-many relationship on the model. Thus you can iterate through them, attach them and involve them in a multiple select in a (IMO) better way.
I would do something like in my model:
has_many :special_options
In my view:
f.select :special_options, :multiple => true
This would avoid the problem of having to serialize and deserialize the objects before storing them.

Related

Rails collection_select with join table

My tables:
Person belongs_to and
Room has_many Person
My collection_select
<%= collection_select(:inspection, :person_id, Person.involving(current_user), :id, :room_id) %>
If I'm not wrong, in HTML it will be represented as the following code:
<select name="post[person_id]">
<option value="<%= person.id %>"><%= person.room_id %></option>
<% end %>
</select>
My point is that when a user submit the form I need send the Person Id value, but I need show on the drop down list the name of the rooms (in my example I showing the room.id) like that:
<select name="post[person_id]">
<option value="<%= person.id %>"><%= room.name %></option>
<% end %>
</select>
How can I do that?
As I see I think that I need join person table with room table? If it is the solution, how can I do that?
My person model:
scope :involving, -> (user) do
where("persons.id = ?", user.id)
end
My view
<%= form_for #inspection do |f| %>
<label>Select</label>
<%= collection_select(:inspection, :person_id, Person.involving(current_user), :id, :room.id) %>
<%= f.submit "Send" %>
I tried to make it as clear as I could.
Consider using select rather than collection_select. This method allows you finer grain control over what is used for id and name of each option.
In your case you'd want something like:
select(:inspection, :person_id, Person.involving(current_user).collect {|p| [ p.id, p.room.name ] }, { ...other method options... })
This allows you to specify the array of option id/name pairs. You get all the people involved using your scope, then iterate over those returning an array for each one found, where the first value in the array is the option value and the second is the displayed option text.
Check this documentation out for more details.

Rails/Ruby - Confused by this enum-related error

I've created a concern that contains an enum listing possible gender values for use in forms and such:
genderable.rb
module Genderable
extend ActiveSupport::Concern
included do
enum gender: [:"Not Known", :"Male", :"Female", :"Not Applicable"]
end
end
Here's where I include it in my model:
user.rb
class User < ActiveRecord::Base
include Genderable
has_one :user_gender
has_one :gender, :through => :user_gender
accepts_nested_attributes_for :user_gender
end
Here's where I use it within my view:
edit.html.erb
<div class="form-group">
<%= f.select :gender, User.genders, :class => "form-control" %>
<%= showErrorMessages("Gender", :gender) %>
</div>
Here's the markup that is generated for my view:
<select id="user_gender" name="user[gender]">
<option value="0">Not Known</option>
<option value="1">Male</option>
<option value="2">Female</option>
<option value="3">Not Applicable</option>
</select>
Here's the error message I get when attempting to submit the form relying upon all of the above:
It seems that ActiveRecord dislikes the fact that the value for gender is a string and not an integer (I'm guessing!). Or maybe it dislikes that the value doesn't match one of the symbol values of the enum I created. I'm really not sure. Does anyone know what the problem is? Basically, I just want to update the user_genders table with the user's ID and the selected value.
You can't assign the integer values to an enum. You need to assign the actual symbol.
For your view, you should use:
<%= f.select :gender, User.genders.keys, :class => "form-control" %>
In order to generate a select that looks like this:
<option value="Not Known">Not Known</option>
<option value="Male">Male</option>
<option value="Female">Female</option>
<option value="Not Applicable">Not Applicable</option>

Is this nested form field mislabeled?

I have the following form code
<%= f.fields_for resource.paid_account do |pa| %>
<%= pa.collection_select :account_plan_id, #account_plans, :id, :name_with_price %>
<% end %>
that generates the following HTML
<select id="user_paid_account_account_plan_id" name="user[paid_account][account_plan_id]">
<option value="2">Lite ($10.00/mo)</option>
<option value="3">Professional ($20.00/mo)</option>
<option value="4">Plus ($30.00/mo)</option>
</select>
Is user[paid_account][account_plan_id] the right name? Shouldn't it be user[paid_account_attributes][account_plan_id]?
I ask because this is causing problems on the backend; my account_plan record isn't getting created.
Looks like this answer is yes. I manually changed the name like this:
<%= pa.collection_select :account_plan_id, #account_plans, :id, :name_with_price, {},
{ name: "user[paid_account_attributes][account_plan_id]" } %>
and now it works. Feels like a hack, though, so it seems like there must be a better way to do it.

Concatenating adjacent form fields into hidden field value in Rails

I want to concatenate two form text field values and assign them to my hidden form field in a Rails view:
<%= f.hidden_field :shortcode, :value => :package :pins %><br />
<div class="field">
<%= f.label :package_type %><br />
<%= select("package", "package_type_id", PackageType.all.collect {|p| [p.packagetype, p.id]} ) %>
</div>
<div class="field">
<%= f.label :pins %><br />
<%= f.text_field :pins %>
</div>
I want :shortcode to return the concatenated values of the :package + :pins values entered into their respective form fields.
How do I do that?
Editing to show code used to implement this as the "answer":
$('#package_pins').blur(function() {
var combined = $('select#package_package_type_id option:selected').text() + $('#package_pins').val();
$('#package_shortcode').val(combined);
});
Added this code to my "packages.js" in app/assets/javascripts dir.
Note that because the package_type selector is pulling in a belongs_to record in the model, the select options get populated like so:
<select id=package_package_type_id name="package[package_type_id]">
<option value="551">FFG</option>
<option value="552">FFC</option>
<option value="553">FTA</option>
</select>
where what I wanted to grab from the "FFG" text, rather than the value "551", which is the record id from ActiveRecord, in this case. I was able to do this by using the option:selected').text() jquery code.
Thanks again to #maprihoda for pointing me in the right direction!
You need to write some client-side Javascript code for this. Using eg JQuery you can easily get the values of the package and pins fields (after the user fills in the pins field), concatenate them, and update the value of the hidden field.
Something roughly like this (you need to add the the right classes to the divs that wrap the fields for this to work):
$('selector for the pins field').blur(function() {
combined = $('selector for the package_type field').val() + $('selector for the pins field').val()
$('selector for the hidden field').val(combined)
})

Ruby on Rails: Submitting a form referring to another controller via collection_select

Today is the first day I'm looking into Ruby on Rails, and now I'm stuck. I have two scaffolds, artist and song.
In songs/new.html.erb, I have these lines:
...
<%= f.label :name %><br />
<%= f.text_field :name %>
...
<%= f.label :Artist %>
<%= collection_select(:song, :Artist, #artists, :id, :sort_name) %>
...
In the form for creating a new song, I want a <select> list with all artists. Using the code above works fine. The form is created as I want it, and the artists are listed. However, when submitting the new song, I get this error:
Artist(#69916999335860) expected, got String(#69917057438720)
The generated HTML code for the select looks like this:
<select id="song_Artist" name="song[Artist]">
<option value="1">Vreeswijk, Cornelis</option>
<option value="2">De lyckliga kompisarna</option>
<option value="3">Wiehe, Mikael</option>
<option value="4">Demian, Lars</option>
<option value="5">Sundström, Stefan</option>
</select>
I guess the second last parameter for collection_select() is wrong, but what should it be?
I think this should be:
<%= collection_select(:song, :artist_id, #artists, :id, :sort_name) %>
The second parameter is the method to be assigned in the model being created/updated. So in your controller the value would be retrieved from the params hash with params[:song][:artist_id]
A detailed explanation can be found in the Rails API docs under "collection_select"

Resources