Select option not preselected after validation using collection in formtastic field - ruby-on-rails

I'm 90% sure I'm doing something obviously wrong here, but when I'm using a select with a collection:
<%= f.input :description,
:label => "Which best describes who you are?",
:prompt => "Select an option...",
:collection => [[ "I am working for a company", "working"],["I am a freelancer", "freelancer"],["I am studying", "studying"],["I have recently graduated", "graduated"],["I teach", "teach"],["None of these things","none"]]
%>
and the form fails validation, the previously selected value is not selected, even though it is saved and is being passed to the params[:user][:description] as expected. Any ideas where I'm going wrong?

It's described there https://github.com/justinfrench/formtastic/wiki/Deprecation-of-%3Aselected-option#what-to-do-instead, so following should work
f.select :description,
options_for_select([[ "I am working for a company", "working"],["I am a freelancer", "freelancer"],["I am studying", "studying"],["I have recently graduated", "graduated"],["I teach", "teach"],["None of these things","none"]], f.object.description)
:label => "Which best describes who you are?",
:prompt => "Select an option...",
Also I would suggest moving collection to a separate helper method

Related

In simple_form, can't submit boolean as radio_button if the field is disabled

I am using simple_form 2.0. I have a Boolean field 'stock' which I am trying to submit as radio buttons.
<%= f.input :stock , :as => :radio_buttons, :collection => [['Purchase Indent', false],
['Stock', true]], label:"Shipments From" , :disabled => true%>
The stock is marked as false before rendering the form.
Once I submit the form the stock itself is missing from the parameter and I get this error.
Because I am validating stock's inclusion.
validates_inclusion_of :stock, :in => [true, false]
It works fine if i don't disable the field. But I don't want user to be able to change it.
Please help.
Update
The reason is that, the disabled fields are never sent. http://www.w3.org/TR/html401/interact/forms.html#h-17.12
Seems like making it read-only will help.
https://github.com/plataformatec/simple_form/pull/367
But, the news is radio buttons can't be made read only.
Why can't radio buttons be "readonly"?
One option is to separate the buttons and only disable the unselected option:
<%= f.input :stock , :as => :radio_buttons, collection: [['Purchase Indent', false]], label:"Shipments From" %>
<%= f.input :stock , :as => :radio_buttons, collection: [['Stock', true]], label:"" , :disabled => true %>
Another option would be to add a hidden input with the desired value.
Remember not to trust user submitted data.
I don't think you should build it like this, because a hacker can just change the HTML / submit an artificial request even if you disable the form elements. Hidden form elements don't fix this, as anyone with a dom explorer can change the values. Of course, if your model checks and rejects this kind of thing it's not such a big problem.
So to fix the particular problem, just do the visuals as you have already, and re-insert the expected value in your controller's update or create action.
For more info there's lots online e.g. owasp, but I liked the book "How to break web software" from a few years back by some guys at Google.

Validates the presence of an option

I have a form that I want to validate if an option has been selected.
I do not want to accept the default starting option, "Please Select a Product"
I using this now and get a uninitialized contant error. I believe I am writing the syntax wrong.
Controller:
validates :product_name, :presence => { :unless => (product_name = "Please Select a Product")}
View:
<span class="span5 pagination-right">
<%= f.label "Product" %>
<%= f.select :product_name, options_for_select([ ["Please Select a Product"] ]) %>
</span>
How am I supposed to have the option written?
Thank you
The product_name is changed like this:
<script>
$(document).ready(function() {
$('#ticket_product_name').html("<option>Please Select a Product</option>");
$('#ticket_firmware_version_string').html("<option>Please Select a Firmware</option>");
$('#category').change(function(){
$('#ticket_product_name').html("<option>Please Select a Product</option>");
$('#ticket_firmware_version_string').html("<option>Please Select a Firmware</option>");
if ($('#category').val() == "blah")
{
$('#ticket_product_name').append("<option>blah</option>");
$('#ticket_product_name').append("<option>blah</option>");
}
else if ($('#category').val() == "another category")
{
$('#ticket_product_name').append("<option>blah product</option>");
}
until end of options, end script.
I think what you are looking for is a placeholder for this select. In this case, I used a disabled option:
<% options = options_for_select(["Select an option", ["Product #1",1], ["Product #2",2]], disabled: "Select an option") %>
<%= f.select :product_name, options %>
You should use include_blank from the select helper, like this:
<%= f.select :product_name, options_for_select([["opt1",1],["opt2",2]]), include_blank: true %>
and then, on model
validates :product_name, :presence => true
#MrYoshiji commented something truthful in my answer - if you are not allowing it to be blank, the easy way is simply not add a blank option in the select
I would recommend to use the :prompt option for your select helper (the documentation on this isn't quite straight forwward, but it's ok in this version of the same thing: http://apidock.com/rails/ActionView/Helpers/FormTagHelper/select_tag). This allows you to define a helper string of text to encourage the user to select an option, but will submit a nil value back when the form is submitted.
<%= f.select :product_name, PRODUCT_NAME_OPTIONS, prompt: 'Select an option' %>
The next thing I'd recommend is... instead of validating presence of on the model, do a validates_inclusion_of. This way you can define the set of options in the model and then use that same set of options in the select helper, above, as well is in your validation. This way you know the form wasn't manipulated to include a different option and it actually keeps things a bit DRYer.
Product
PRODUCT_NAME_OPTIONS = {'opt 1' => 'opt1', 'opt 2' => 'opt2'}
validates_inclusion_of :product_name, :in => PRODUCT_NAME_OPTIONS.values, :message => 'choose from the available options'
Instead of making this too complicated, I just added a length validation since the default is much longer then the product names. Simple is best, however there should be a string validator option.
validates :product_name, presence: true, length: {
maximum: 21,
too_long: ": Must select a product"
}

Rails formtastic is asking for a country plug-in.. I don't want it. Anyone know how to tell it I don't want it?

I'm using formtastic and I've got a field country.. I'm getting this error when I attempt to display the screen.
To use the :country input, please install a country_select plugin,
like this one: https://github.com/jamesds/country-select
Now. I don't want to use any plugin.. It's free text, and I want to keep it that way.
Anyone know how to remove this requirement? Should be easy as... but I'm buggered if I can see how.
= semantic_form_for #store, {:html => { :class => "form-horizontal" }} do |f|
= f.input :default_country
Add
, :as => :string
to the end of the line that's causing the error
= semantic_form_for #store, {:html => { :class => "form-horizontal" }} do |f|
= f.input :default_country, :as => :string
In Rails 4, formtastic with country select input field:
Add 'country-select' to your Gemfile:
gem 'country-select'
If I use semantic form select, it doesn't shows previously saved value. So, the following is not working properly:
=f.input :country, as: :select, collection: country_options_for_select
So have to use standard form elements to get working:
=f.select :country, collection: country_options_for_select
I found that this plugin works out of the box (note the underscore instead of the dash):
https://github.com/chrislerum/country_select

How to set a field read only in rails 3.1.0 views?

My question is how to set a field in rails form read only. The following is a selection box in quotes controller. Users are not allowed to change the selection.
<% #quote.test_items.each do |t| %>
<%= f.association :test_items, :label => false, :selected => t.id %>
<% end %>
The app uses simple_form. Thanks so much.
I've encountered a similar problem, thankfully, there is a simple resolution.
The basic issue is that if you use :disabled => true with simple_form you will not see that value back in the controller. When you pass an object from HTML form to later bind it to the model - you need all of those attributes. The :disabled => true however does not pass any such attribute.
The solution to this is to use :readonly => true - it will protect the field from user entry and it will still pass the param value back to the controller so you can bind everything to your model.
Good luck.
See https://github.com/plataformatec/simple_form/pull/367
I believe you'd just pass in :disabled => true. It's been my experience that options 'just work' with simple_form. So in your case:
<% #quote.test_items.each do |t| %>
<%= f.association :test_items, :label => false, :disabled => true, :selected => t.id %>
<% end %>
From the simple_form github repo:
It is also possible to give the :disabled option to SimpleForm, and it'll automatically mark the wrapper as disabled with a css class, so you can style labels, hints and other components inside the wrapper as well.
Yes, what #gk0r said, as it is documented here:
NOTE: The HTML options disabled, readonly, and multiple can all be treated as booleans. So specifying :disabled => true will give disabled="disabled".
*disabled will have slightly different behavior than readonly.
The top answers above are all wrong.
disabled attribute has a different behaviour than readonly.
read and compare them:
http://www.w3schools.com/tags/att_input_disabled.asp
Tip: Disabled elements in a form will not be submitted.
http://www.w3schools.com/tags/att_input_readonly.asp
The right answer is to use
:readonly => true
something like this:
<%= f.association :test_items, :label => false, :readonly => true, :selected => t.id %>
It's not clear to me if the association method accepts HTML options or not, but if it does, you can pass disabled: 'disable' to make it read-only with a fixed value.
I think you might be able to choose the fixed value by passing association as block, as shown in the association docs:
f.association :company do |c|
c.input :name, selected: 'selection'
c.input :type
end
As to whether or not the entire list can be read-only and still drop-down, the only solutions I see from google involve JS, for example:
http://techeyes.blogspot.com/2007/11/making-html-select-readonly.html

Rails, collection_select - remembering values with :selected after form submitted

(Using Rails 2.3.5 on an internal work server with no choice of versions, and I'm pretty new)
I'm building a search form where I need to provide a list of directories to a user so they can select which one(s) to search against. I'm trying to figure out how to get the selected values of a collection_select to remain after the form is submitted.
Say the user selected 3 directories from the collection_select, the id's of those directories would look like this in the params:
directory: !map:HashWithIndifferentAccess
id:
- "2"
- "4"
- "6"
I know that you can manually specify multiple selected items:
<%= collection_select :directory, :id, #directories, :id, :name,
{:selected => [2,4,6]}, {:size => 5, :multiple => true} %>
I've also played around a bit and was able to us "to_i" against a single value in the params hash:
<%= collection_select :directory, :id, #directories, :id, :name,
{:selected => params[:directory][:id][0].to_i}, {:size => 5, :multiple => true} %>
What I can't figure out is how to use all of the values of the :directory params at the same time so what the user selected remains after the form is submitted. Thanks for any help.
I'm not precisely sure what you're asking, but if you're trying to get the array of strings in params[:directory][:id] as an array of integers, all you need is
params[:directory][:id].map{|id|id.to_i}

Resources