Stored value not being set to nil when user deselects all options - rails / simple_form - ruby-on-rails

I have the following form input which is working, except for one small 'bug'
<%= f.input :secondary_role, :collection => UseridRole::VALUES, :include_blank => false,:label => "Secondary Role(s):", :input_html => { :class => " simple_form_bgcolour simple_form_position overide_selection_field_width", :size => 4, multiple: true }, include_hidden: false, :hint => "Hold shift to select multiple roles" %>
My user's secondary role is stored in my DB as an array:-
"secondary_role": ["moderator"]
My problem is that in cases where the user has set a secondary role, that can't be un-set by deselecting the option. Nothing happens when an option is deselected in the list and saved. The above moderator can only be removed by selecting another option. How can I make the array empty upon deselection of all?

Remove the include_hidden: false option; the hidden field is there to make this work automatically.
(Otherwise, you'll need to handle the situation manually in the controller action that receives the form submission.)

So as #matthewd pointed out, the solution was to remove the include_hidden: false option, although this introduced another issue of a blank array item being added to my roles array.
So, I added the below method to trigger before every save and remove any blank array entries:
def remove_blank_entry
secondary_role = self.secondary_role
if secondary_role.include? ""
secondary_role.delete("")
end
end

Related

How to set association checkboxes to true by default in Rails

I want to check my association checkboxes by default. I tried by setting the checked attribute to an array of plucked Company IDs.
= f.association :selected_companies, label_method: :name, as: :check_boxes, collection: Company.order(:name), :checked => Company.pluck(:id)
This seems to work, but when there are form field errors, the checkboxes are reset on the next request. I'd like to persist the users choice in these cases.
Any ideas?
Change your view to checked: #company_ids and then in your controller set that to Company.pluck(:id) in your edit action, but to #your_main_object.selected_company_ids in your update action.

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.

Rails check box resetting to default

I have a few check boxes in my view set to default as active:
<%= check_box "product[pr_attributes]", "ag_type", {:checked => #product.issenior?, :multiple => true, :checked => true}, checked_value = "ag:senior", unchecked_value = nil %>Senior(65-100)
The problem is, when I uncheck one of the defaults and save the changes, it defaults back to the checked state. How can I solve this?
Did you mean to have two option keys for :checked?
Mostly like the second one :checked => true is causing your problem.
i think the best way to do this in your case is use check_box_tag since your doing multiple answers for one attribute
syntax
check_box_tag "id", "value", "boolean_if_checked"
so in your case:
<%= check_box_tag "product[pr_attributes][]", "ag_type", #product.issenior?, { } %>
Then just add the other attributes on the hash after the #product.issenior?
This way, you can create multiple checkboxes for pr_attributes, and then when you submit the form, pr_attributes will be an array of your choices.

Preselect Check box with Rails Simple_form

I'm using Simple_Form with Rails 3 and it's great. I have a simple question. I can create a check box using f.input if the type is boolean behind the scenes. However, I would like it to be preselected as true.
Is there a way to do this via the view?
If you don't want to, or cannot update your migration to do 'PerfectlyNormal's answer, then you can add the following to the end of your f.input:
:input_html => { :checked => true }
So, it would become:
= f.input :some_flag, :input_html => { :checked => true }
the best way would be to set the default value in your model, something like
create_table :my_table do |t|
...
t.boolean :my_boolean, :default => true
...
end
which simple_form will pick up on, and set the checkbox to be checked by default.
A simpler way is to do it as Dave says, and just force the value to 1, but if a validation fails, and you display the form again, it will still be checked, regardless of how it looked when the form was submitted.
It Worked for me which checks only one checkbox with value of "None"
<%= f.input :notify, label: "Notification", as: :check_boxes, collection: ["None", "Daily", "Weekly", "Monthly", "Quarterly", "Yearly"], :item_wrapper_class => 'inline', :checked => ["None", true] %>
I just stumbled over this post and what worked for me is similar to the latest answer - but shorter. Just initialize the Object with the wished setting:
def new
Object.new(my_boolean: true)
end
In my opinion, the rail way to do this would be to set the value of the attribute in the controller:
#some_object.some_flag = 1
This should work:
= f.input :some_flag, :input_html => { :value => '1' }
If you do the following, as in the highest rated answer (and as noted by #PerfectlyNormal) you are essentially hard-coding the state for every page load:
= f.input :some_flag, :input_html => { :checked => true } # don't do this
If you are using Rails-style server validation, this will have the unintended side effect of resetting the user's choice when validation fails.
Defaulting it in the model is ideal if the default value is static. In some cases though, the default value is driven by some business rule, so setting it at runtime is desired. For example, in my case, I wanted to default a checkbox to true, but only for certain types of organizations.
What you want is to default the value only when it is not already set, otherwise use the user-selected value. Here's how I handled this:
- is_checked = #org.is_special.nil? ? true : #org.is_special?
= f.input :some_flag, :input_html => { :checked => is_checked }
For Rails 6+, you can simply do:
<%= f.check_box :remember_me, checked: true %>

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