Reputation: 5897
I'm having a lot of trouble getting a simple true/false to evaluate properly in Rails. I have this in a helper:
def should_we_ask_to_subscribe?
if @user.email.blank?
true
elsif @user.subscriber == false
true
else
false
end
end
I test for blank because the user object is created by omniauth and sometimes, as with Twitter, I don't get an email. After the authorization is created, the user is directed to update their profile and add an email. If there's no email, I make sure to present the option to subscribe because they can't be subscribed. This is the view:
<% if should_we_ask_to_subscribe? %>
<div class="field">
<%= f.check_box :subscriber %>
<%= f.label :subscriber, "It's okay to send me the occassional email. I know I can unsubscribe at any time." %>
</div>
<% else %>
<div class="field">
You're subscribed to our email list.<br />
<%= f.check_box :unsubscribe %>
<%= f.label :unsubscribe, "Please unsubscribe me." %>
</div>
<% end %>
However, even when the subscribe boolean is set to f
-- say a user has entered an email, but not subscribed (or unsubscribed, which is the only way the boolean would be f
) should_we_ask_to_subscribe?
still evaluates to false. I've tried various permuations but am just not getting it.
Okay, so it's clear that the database is storing the boolean value as false, but rails is interpreting it as true and I can't really get why. Following advice below with inspect, the log shows @user.subscriber = true even though in the console and in the database I get subscriber: false for that particular user.
So I've written some unit tests and they all pass. In my logs, I notice the code is doing the following:
(0.4ms) UPDATE "users" SET "subscriber" = 'f', "updated_at" = '2011-07-05 13:40:58.178186' WHERE "users"."id" = 47
and this is the code, in a method in my model, that does that:
self.update_attribute(:subscriber, false)
When I look at the database, both through an SQLite view and the console, I see an f
and u.subscriber => false
, respectively. But, when I use logger.info "@user.subscriber = #{@user.subscriber.inspect}"
to see how the view helper is interpreting it, I get: @user.subscriber = true
in the log. So, I'm assuming the problem is with how I set false
since it seems rails is interpreting any value in the subscriber column as true (except in the console, where it seems to be saying its false?).
Upvotes: 1
Views: 1855
Reputation: 12830
Diagnose whether the value of subscriber is not nil
(which is a false equivalent) or whether it is not any other value.
Put this line in the should_we_ask_to_subscribe
function:
logger.info "@user.subscriber = #{@user.subscriber.inspect}"
Is your subscriber
attribute declared as boolean? The checkbox would send a value of "0" (a string), which will evaluate to true in ruby, but usually is magically translated to 'false', but only for boolean attributes.
Upvotes: 1
Reputation: 211590
This is a good candidate for a unit test that will exercise your model and determine if the correct behavior is implemented. For instance:
@user = User.create(...)
assert @user.email.blank?
assert [email protected]?
assert_equal true, @user.should_we_ask_to_subscribe?
@user.email = '[email protected]'
assert_equal false, @user.should_we_ask_to_subscribe?
@user.unsubscribe = true
assert_equal true, @user.should_we_ask_to_subscribe?
As a note, if you're dealing with variables that are interpreted as either true or false, you don't need to be so formal about comparing values to false specifically. A simple refactoring would look like this:
def should_we_ask_to_subscribe?
# Show subscription option if no email has been provided.
return true if @user.email.blank?
# Otherwise ask to subscribe if not a subscriber
[email protected]?
end
Upvotes: 2
Reputation: 339
I am currious to see in what way the subscriber field information is saved in your database.
Could you raise @user.subscriber within your should_we_ask_to_subscribe? function please?
Upvotes: 0