Compare checkbox with boolean

Hi!

I have a form with a checkbox called “status” which is a boolean in the database.

In my controller’s update action I want to check if the checkbox has changed. Something like this:

if @item.status != params[:item][:status]
params[:item][:position] = nil

end

But this doesn’t work as the params[:item][:status] is “0” (an int as a string)

And the @item.status is false/true (a bool)

I have tried to use the .to_i on the status param to make it into an int, but it still doesn’t work. I guess there is no .to_bool? :slight_smile:

So, how do I do this comparison? I’m new to Rails and these small things makes be a bit puzzled :slight_smile:

Tried to use .to_i on the both?

Yes, it gives me this error:

NoMethodError (undefined method `to_i’ for false:FalseClass):

Try @item.status != !params[:item][:status].to_i.zero?

Yes, ended up doing this:
!@item.status != params[:item][:status].to_i.zero?

But it looks very ugly to me…

after update do

if @item.status_changed? ...

Hmm, that seems to always return false over here.

I tried this:
update_was_successful = @item.update_attributes(params[:item])
puts @item.status_changed?

Which outputs false, always. The weird thing is that it prints that before the update is shown in the console. I guess that is why it’s always false.

Isn’t the update_attributes method updating the item right away?

Since the params will give you either "0" or "1" as a string, and
since you are trying to equate "0" (string) to "false" (boolean), why
not set a variable equal to "true" or "false" based on the params?
Try:

if params[:item][:status] == "0"
  bool = false
else
  bool = true
end

or,

bool = (params[:item][:status] != "0")

You can then compare bool to your boolean.

Yes, but that doesn’t look very good either. Not much better than doing this I’m afraid:

!@item.status != params[:item][:status].to_i.zero?

Or put something like this in an initializer:

Or this may be helpful:

def convert_to_boolean(value)
  return [true, "true", 1, "1", "T", "t"].include?(value.class ==
String ? value.downcase : value)
end

No, you really shouldn't be doing that in the controller. You almost
certainly want to do this in a before_save (or possibly
before_validation) callback on the MODEL.

Several reasons:

- it's a best practice to keep business logic in the model ("fat
model / skinny controller")

- inside the model callbacks, you've got access to both typecast data
(the incoming status will already have the right type) and the
_changed? predicate. For instance, your code could be shortened to:

class Item < ActiveRecord::Base

  before_save :update_position

  def update_position
    self.position = nil if status_changed?
  end

end

Not only does it avoid the messy conversion, it (IMHO) is far more
readable.

--Matt Jones

That is very true. Thank you for that!

I ended up changing the behavior though, so I didn’t need to check if the status had changed at all.

Best Regards

Linus