Rails form_for setting options and setting selected option - mysql

Another simple question i'm sure so sorry in advance but i cant seem to find a solution to what i am trying to do.
I have form with a select field (vehicle_size) that i want to populate with all existing options that are currently in the database for records that have vehicle_size set. I also want to set the selected option to whatever the option in the database is currently set to (if set) but i guess the problem that i am having is the reason that this value isn't being set already.
I currently have this code:
<%= f.select(:vehicle_size, #models.index_by {|m| m.vehicle_size}, :selected => :vehicle_size) %>
which is populating the select options correctly but in my new and edit pages (both using this form) the select menu is blank even though currently all records are be set to one of the existing options (vehicle_size may actually be blank for some records in future).
If i then select an option from the menu and save the record the vehicle_size option has a strange value. something along the lines of :
#<Model:0x007fd13e6c3790>
I'm pretty sure i'm using index_by in the wrong way so some pointers on what i'm missing would be great.

The parameters of f.select are: attribute_name,option_tags,options.
option_tags is supposed to be a string of html option tags.
There are some helpers to construct such a string from i.e. an array of values, a collection etc.: options_for_select, options_from_selection_for_select.
You have to use one of these helpers.
You can get the existing vehicle_sizees with:
Model.pluck(:vehicle_size).uniq
so your select could look like:
<%= f.select :vehicle_size, options_for_select(Model.pluck(:vehicle_size).uniq,#model.vehicle_size) %>
See the Rails Guide on form helpers.

Related

How to get value from select and use it in Rails

I'm starting a little project in rails and I'm trying to make something like that:
<%= f.label :Zgłoszenie_do_działu %>
<%= f.collection_select :dzial_id, Dzial.all, :id, :nazwa, prompt: "Wybierz" %>
<%= f.label :id_pracownik %><br/>
<%= f.collection_select :pracownikid, User.find_by_dzial_id(:dzial_id), :nazwa, prompt:"Wybierz" %>
I want to get ID of "dzial" from the first select and use it to display in the second select IDs or names of users, that belong to choosen "dzial". Like you can see I was trying to make something, but anything worked for me. If it isn't possible I would be thankful, if anybody would show me how to deal with it.
If I do understand you properly, you have the following usecase: On your page you select a dzial and after that the second select field has to show all it's User ids.
Without refreshing the page
If you want to do this without refreshing the page, you can't really do it the 'rails way'. You could use for example jQuery to do an asynchronous call on change of the first select field. Then you can use the result of that call to update the second select field.
With refreshing the page
If you want to do this by only using ruby-on-rails you could trigger a refresh on the change of the first select or simply create a submit button. Then you can set the dzial_id parameter and use it to fill the second select field like you are already doing in your example.
Edit
I forgot to mention how to get the value from the select field.
By using jQuery, you could use $('#dzial_select').val()
By refreshing the page, you might want to create two seperate forms

Need Validation on html dropdownlist with data from Viewbag

I know I'm not supposed to use the Viewbag and that I should build a menu using Html.DropDowlListFor() so that i can add attribute bound to the members of the model, BUT, that would involve a pretty extensive code rewrite....
I have a custom controller with a menu:
*.ASCX
<%: Html.DropDownList("CityIDs", new SelectList(ViewBag.cities, "Id", "Name"), "--Select--", new { style = "width:200px" })%>
<%= Html.ValidationMessage("CityIDs") %>
The List populates just fine and I can default to the top item to "--Select--"
The prbolem is that I want the validation error to occur on anything that is not from the viewbag.... how can I achieve this?
Validation for dropdown lists only ensures that something was posted. If you want to ensure that the value that was posted is actually one of a set of "allowed" values, then you'll have to manually do that in your post action:
var cityIds = db.Cities.Select(m => m.Id);
if (!cityIds.Contains(model.CityIDs))
{
ModelState.AddModelError("CityIDs", "You must select one of the available choices.");
}
if (ModelState.IsValid)
{
...
Two things:
Notice that I'm pulling the city ids straight from the database (the actual code you'd need here, of course, depends on your specific implementation). The important thing, though, is that ViewBag only survives a single request, so you can't look for them in ViewBag after posting.
Despite the pluralized name of CityIDs, using the DropDownList helper ensures that only a single selected value will exist. If this is actually supposed to be a multiselect, then you need to use ListBox instead, and update this conditional here to account for check for multiple values.
Populates the top item with Text = "--Select--" and Value = ""
which will post a blank value for CityIDs and cause an error in ModelState.

unescape HTML in options for select

I've got a select tag, which is used to change the filter via the URL. On change I reload the page to update the results accordingly. The newly selected filter should obviously appear as selected. But this fails to work.
<%= select_tag("filter_rating" , (:selected =>) options_for_select(rating_filter_options, (request.env['PATH_INFO']))) %>
I deleted the (:selected =>) as it seems unnecessary.
rating_filter_options value:
# [["by my rating", "/all"], ["1+", "/rating%3E=1"], ... , ["5", "/rating%3E=5"]]
The reason why the current filter will not get selected is that request.env['PATH_INFO'] returns /rating>=1, which is different than /rating%3E=5. So the solution would be to unescape that nasty %3E.
I tried using CGI.unescape, h, html_safe on the select tag, but so far my attempts have failed.
Any ideas?
Update:
I changed the helper that generated the rating_filter_options and placed the CGI.unescape correctly so it now returns:
# [["by my rating", "/all"], ["1+", "/rating>=1"], ... , ["5", "/rating>=5"]]
Also, I use CGI.unescape for the request.env['PATH_INFO'] to make sure it is the same. The result in logs & HTML approve that it is correct now. BUT the selected filter still does not get selected...
CGI should work.
irb(main):112:0> CGI.unescape("/rating%3E=1")
=> "/rating>=1"

Disable DropDown in Rails

I want to disable an HTML DropDown in Rails, and I found this solution:
how to disable the entire dropdown control in html
So, I have this:
f.select( ...., :disabled => true)
But, the problem is, when the DropDown is disabled, it does not show in the params collection.
EDIT:
This is my situation:
I have a form with a text_field and a select field. There are two cases:
The user creates a new item directly. If so, she will choose a category from the select field.
The user creates a new item, after redirecting from a category page. In this case, the select field is set to the value of the category, and should be disabled.
Does anyone have any idea how to fix this?
As mentioned in my comment in the original question, disabled form element values won't be present in the params on a form submission. To get around this, try using a hidden field to hold and submit the value you want.
Assuming some variables and whatnot are setup to help decide whether the select field should be disabled:
# ...
f.select(..., :disabled => #category_already_chosen)
f.hidden_field(...) if #category_already_chosen
# ...
Obviously this can be changed to suit your needs, but the basic idea is there. If you've already chosen a category and want the select field to be disabled, make a hidden field. If you haven't chosen a category, omit the hidden field and allow users to make use of the select field.
As shown in the link I posted, this is probably the simplest way to get around this limitation, without resorting to using Javascript to play with parameters after form submission.
I would add query string parameters to your redirect_to call
redirect_to :action => form_path, :category => :whatever_category_they_came_from, :disabled => true
Then in your form
:selected => params[:category], :disabled => params[:disabled]

Select Box not filling properly in rails

I am creating a select box for a form using this in _form.html.erb
<%= f.select(:category_id,options_for_select(#cats)) %>
#cats is an array created in my controller like this:
#cats = []
categories.each do |c|
#cats.push([c.full_name,c.id])
end
The select box is properly filled, and the selected foreign key is even properly saved to the database. The problem is, when I come back in my edit action, the select box is moved back to the first item in the list, not the one corresponding to category_id. Reading the documentation it seems like this should just magically work. How do I get it to select the proper value?
When you use the select helper you just pass the choices not the full option tags like you would with the select_tag helper. Try this instead
<%= f.select(:category_id, #cats) %>