【问题标题】:Value stored in boolean column as false is evaluated as true by Rails?Rails 将布尔列中存储为 false 的值评估为 true?
【发布时间】:2011-07-04 14:20:55
【问题描述】:

我很难在 Rails 中正确评估一个简单的真/假。我在助手中有这个:

 def should_we_ask_to_subscribe?
    if @user.email.blank?
      true
    elsif @user.subscriber == false
      true
    else
      false
    end
  end

我测试空白是因为用户对象是由omniauth 创建的,有时,与Twitter 一样,我没有收到电子邮件。创建授权后,将引导用户更新其个人资料并添加电子邮件。如果没有电子邮件,我会确保提供订阅选项,因为它们无法订阅。这是视图:

<% 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 %>

但是,即使订阅布尔值设置为 f - 假设用户输入了电子邮件,但未订阅(或取消订阅,这是布尔值将是 f 的唯一方式)should_we_ask_to_subscribe? 仍然评估为假。我尝试了各种排列,但就是不明白。

更新

好的,很明显数据库将布尔值存储为 false,但 rails 将其解释为 true,我真的不明白为什么。按照下面的检查建议,日志显示 @user.subscriber = true 即使在控制台和数据库中我得到subscriber: false 对于该特定用户。

第二次更新

所以我编写了一些单元测试,它们都通过了。在我的日志中,我注意到代码正在执行以下操作:

(0.4ms)  UPDATE "users" SET "subscriber" = 'f', "updated_at" = '2011-07-05 13:40:58.178186' WHERE "users"."id" = 47

这是我模型中的方法中的代码:

self.update_attribute(:subscriber, false)   

当我通过 SQLite 视图和控制台查看数据库时,我分别看到了 fu.subscriber =&gt; false。但是,当我使用logger.info "@user.subscriber = #{@user.subscriber.inspect}" 查看视图助手如何解释它时,我在日志中得到:@user.subscriber = true。所以,我假设问题在于我如何设置false,因为似乎 rails 将订阅者列中的任何值都解释为 true(除了在控制台中,它似乎在说它是 false?)。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.1


    【解决方案1】:

    这是一个很好的单元测试候选者,它将锻炼您的模型并确定是否实现了正确的行为。例如:

    @user = User.create(...)
    
    assert @user.email.blank?
    assert !@user.subscriber?
    
    assert_equal true, @user.should_we_ask_to_subscribe?
    
    @user.email = 'test@example.email'
    
    assert_equal false, @user.should_we_ask_to_subscribe?
    
    @user.unsubscribe = true
    
    assert_equal true, @user.should_we_ask_to_subscribe?
    

    请注意,如果您正在处理解释为真或假的变量,则不需要如此正式地专门比较值与假。一个简单的重构如下所示:

    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
      !@user.subscriber?
    end
    

    【讨论】:

      【解决方案2】:

      判断subscriber的值是不是nil(这是一个假等价物)还是不是任何其他值。

      将此行放入should_we_ask_to_subscribe函数中:

      logger.info "@user.subscriber = #{@user.subscriber.inspect}"
      

      您的subscriber 属性是否声明为布尔值?该复选框将发送一个值“0”(一个字符串),在 ruby​​ 中该值将评估为 true,但通常会神奇地转换为“false”,但仅适用于布尔属性。

      【讨论】:

      • 这很有趣。日志显示@user.subscriber = true,即使在控制台中我得到该特定用户的subscriber: false
      • 可能意味着该属性在控制器中发生了变化,但没有保存到数据库中。仔细检查日志,看看是否有 SQL 命令“插入”或“更新”的迹象。正如 Tadman 建议的那样,编写一个单元测试,然后您可能想要编写一个功能测试,这将显示控制器的不正确行为(如果这是控制器的问题)。测试后,尝试在代码中查找错误。也许对象无效,但不知何故没有显示错误?
      • 另外,'false' 值是真正的 ruby​​ 布尔值,还是一个内容为 "false" 的字符串?好吧,我只好问了。请不要感到被冒犯。 ;)
      • 好的,我已经在这里更新了帖子,回答了您的想法。我不认为这是一个字符串,但我有点想看看有什么问题。
      【解决方案3】:

      我很想知道订阅者字段信息以何种方式保存在您的数据库中。

      你能在你的 should_we_ask_to_subscribe 中提出@user.subscriber 吗?请问功能?

      • 在函数顶部添加: 提高@user.subscriber.inspect

      【讨论】:

      • Users#edit 中的 RuntimeError 显示 /Users/justin/Code/publicizr/app/views/users/_form.html.erb 其中第 21 行出现:true
      • 我在开发中使用 SQLite。 Postresql 计划用于生产。
      猜你喜欢
      • 2018-08-17
      • 2015-03-15
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 2011-07-31
      • 2012-11-22
      • 1970-01-01
      相关资源
      最近更新 更多