How can I get a set of radio buttons to accept NULL (nothing checked)?
I'm working on a Rails application where I have some a set of two radio buttons where users can click "yes" or "no". The MySQL DB column created by the ActiveRecord migration开发者_高级运维 is a tinyint.
If the user doesn't click either radio button I want MySQL to store NULL
. (The column allows NULL.) And when they come back to edit the data, neither button should be checked.
What's happening is that ActiveRecord is storing 0
and then when I come back the "No" button is checked.
Rails 2.3.5
Form code (I'm using Haml):
= f.radio_button( :model_attribute, true )
Yes
= f.radio_button( :model_attribute, false )
No
(In retrospect it probably would have been better to use a single checkbox, but it would be difficult to change that now.)
I ran into a problem like this with ASP.NET MVC. Since null
is essentially a third possible state, I added a third hidden radio button that is selected by default. When my response contained the "null" radio button response, I manually set it. I'm not sure if this is exactly what you are going for or not, but it worked quite well for my situation.
Here's my take. I want the user to be able to unselect true/false and set the attribute to nil (Rails 4):
form
= f.radio_button :accepted, true
= f.radio_button :accepted, false
= f.radio_button :accepted, 'nil'
controller
def widget_params
if params[:widget][:accepted] == 'nil'
params[:widget][:accepted] = nil
end
params.require(:widget).permit(:accepted)
end
This seems to defeat the idea of radio buttons (i.e., choose one out of a set). If it is important to track "no response", then would it be possible to add a third radio button for this option? If you don't want the user selecting a response and then re-selecting "no response", you can selectively choose to display the button on your form based on its current value.
How about adding :default => null
to the ActiveRecord migration for the column?
I just checked it myself and it just works as you want. Are you sure there's no code in your update action or your model that changes the attribute? If there's no radio selected in your form, the params hash will have no value for that attribute and the record will keep its previous value. Check you model for an attribute writer method or callback methods.
Judging from your response to my comment that seems to be the behavior you want so this doesn't seem to be a UI problem but instead a problem with your model. It looks to me that calling YourModel.create() would create a DB entry with a 0 in the column.
Possibly you could fix this by defaulting model attribute to nil in your constructor because it appears that ActiveRecord will default it to false for you.
class YourModel
def initialize
self.model_attribute = nil
end
end
However, if you really want 3 options Yes, Not or Not Set then you should probably just change model_attribute from a boolean to an "enum" where 0 means "Not Set", 1 means "Yes" and 2 means "No".
I have solved this today in the following (simplified) example. It's not perfect, but it seems to work for me :) There must be a simpler way to circumvent Rails not sending through the param for radio buttons that do not have a value selected...
In the controller:
def create
params[:post] = Post.deselect_radio_buttons(params[:post])
@post = Post.new(params[:post])
if @post.save
redirect_to post_path(@post), notice: 'Post created'
else
render action: :new
end
end
in the model:
# Define the fields that are used as radio buttons in the form.
RADIO_BUTTONS = [:field1, :field2]
def self.deselect_radio_buttons(params)
RADIO_BUTTONS.each do |field|
if params[field].blank?
params[field] = nil
end
end
return params
end
精彩评论