Ruby on rails Rails选择具有空值的布尔值

Ruby on rails Rails选择具有空值的布尔值,ruby-on-rails,select,null,Ruby On Rails,Select,Null,首先是环境: Rails 2.1.0、Ruby 1.8.7、Mysql 5.1.54、Ubuntu 11.04 我的表中有一个以NULL开头的布尔字段,但我找不到一个好方法将它设置为NULL。(该字段基本上是一个yes/no/unanswered字段,true/false/null似乎适合该字段。客户明确表示希望它能够保持null(unanswered)。) 以下是我的迁移(替换了特定名称): 我的视图有一个select(我认为这是导致问题的原因,表单帮助器selects从来都不好): 但这不是

首先是环境:

Rails 2.1.0、Ruby 1.8.7、Mysql 5.1.54、Ubuntu 11.04

我的表中有一个以NULL开头的布尔字段,但我找不到一个好方法将它设置为NULL。(该字段基本上是一个yes/no/unanswered字段,true/false/null似乎适合该字段。客户明确表示希望它能够保持null(unanswered)。)

以下是我的迁移(替换了特定名称):

我的视图有一个select(我认为这是导致问题的原因,表单帮助器selects从来都不好):

但这不是正确的方法。我遗漏了什么?


<%= f.select :question, options_for_select([["Yes", true], ["No", false]], :question) %>

我认为只有在服务器端才能做到这一点,因为发布数据时总是不是零。因此,您的解决方案是正确的

如果你想避免那些难看的代码,你可以在客户端使用javascript做一些小动作。事实上,如果您使用一个禁用的元素而不是一个空白值,该值将不会被发布,并且您将在服务器端得到
nil

为此,您可以添加一个提交回调,该回调检查问题字段是否为空,如果为空,则在发布数据之前禁用该字段。这样,它将在没有任何服务器端代码的情况下工作

要使用jQuery禁用元素,您可以看到。因此,假设您的表单具有
#表单
id,则可以使用此代码

$(function() {
  $('#form').submit(function () {
    if ($('question-selector').val() == "") {
      $('question-selector').attr('disabled', true);
    }
  })
});

我也有同样的问题,我需要默认为空值的布尔值来表示“未回答”

在Rails 3.2中,当我为布尔值(空白选项)传递“”时,会将db中的列设置为NULL


所以,新版本的rails解决了这个问题:)

@vdaubry我只想补充一点,它并没有真正解决。它被屏蔽了,因为您在UI中使用了“选择”。如果你像我一样愚蠢地使用复选框(毕竟,它们是布尔值,对吗?),那么你在db中的默认nil值(我们的意思是表示“未知”的值)在视图中渲染时会转换为“false”,在db中转换为false,即使它在视图中没有更新,如上所述。换句话说,继续依赖第三个值来保持“boolean”的一致性有点脆弱

此外,如果报告此属性,如果“unknown”是一个有效的含义且不清楚,则报告代码无法轻松推断数据库中的值


因此,我选择重构所有布尔值,使其成为字符串(“是”、“否”、“未知”),并在视图中使用单选按钮。请注意,这仅适用于数据收集UI之类的东西,用户没有时间找出真相,因此从统计学上讲,如果它是“未知”的,那么它非常重要。

我刚刚遇到了同样的问题,我通过将属性转换为空来解决它。在您的情况下,我将向您的模型类添加一个方法

class Client < ActiveRecord::Base
  def question=(value)
    value = nil if value == ''
    super(value)
  end
end
class客户端

这适用于创建和更新。(我使用的是Rails 2.0.5。)

这在之前的文章中没有提到,但是在Rails 5中,如果您想命名为nil选项,这应该是可行的

<%= f.select :question, [["Yes", true], ["No", false]], { :include_blank => 'Name this whatever you want, it will be nil when submitted', :selected => @client.question } %>
“无论您想怎么命名,提交时都将为零”,选择=>@client.question}%>

在我自己的项目中测试了这一点

我认为,仅以我现在的方式验证服务器端没有使用javascript那么复杂和简单;不过,还是要感谢你提出的另一个想法@d3vkit您仍然需要服务器端验证,我的技巧是从params散列中删除空字符串,因为当您使用post请求发送一些数据时,它始终是一个字符串,不能为零。因此,js代码是控制器检查的替代方案,但代码的其余部分(控制器和模型)必须保持不变。因此,也许我仍然头脑不清醒,但您完全删除了参数,然后在控制器中重新添加它,如果它不存在(假设它是零的?)如果你真的需要发送一个空字符串参数,这会有什么好处?在这种情况下,这似乎是客户机的额外工作,而服务器的工作不会减少,除非我误解了。然而,我认为你的观点“post数据总是一个不能为零的字符串”回答了这个问题。谢谢@d3vkit只是为了澄清js仅当参数为空时才删除它。您不需要在控制器中再次添加它,因为如果删除了它,更新属性调用将不会设置相应的字段。因此,如果选择一个值,该值将填充模型属性,否则字段最终将包含nil(即SQL语言中的NULL),我决定只使用整数和enum_fu,因此0=未知,1=否2=是。这似乎是这个特定问题的最佳解决方案,但更广泛的问题是“如何使用带null的布尔值”,我认为Fabio回答得很好。这是使用rails吗?它呈现一个值为0的隐藏复选框,这实际上会转换为数据库中的“false”保存。没有这样做,而且“HTML规范说未选中的复选框不成功,因此web浏览器不会发送它们”,因此它们不会被更新。这与“复选框”相同吗?它的行为似乎是一样的——在浏览器中检查html时,我确实看到了值为“0”的隐藏字段。耶,f。复选框与复选框相同。如果查看格式:
复选框(object\u name,method,options={},checked\u value=“1”,unchecked\u value=“0”)
,表单生成器对象(f)正在替换object\u name。因此底线是,视图中的不同控件将导致不同的模型数据(如果试图依赖“nil”表示“未知”或“未回答”)。这似乎有点冒险。我宁愿不依赖(使用一个或另一个控件)来获得可靠的模型数据;一切都正常运转。
复选框将始终为
<%= f.select :question, options_for_select([["Yes", true], ["No", false]], :question) %>
$(function() {
  $('#form').submit(function () {
    if ($('question-selector').val() == "") {
      $('question-selector').attr('disabled', true);
    }
  })
});
class Client < ActiveRecord::Base
  def question=(value)
    value = nil if value == ''
    super(value)
  end
end
<%= f.select :question, [["Yes", true], ["No", false]], { :include_blank => 'Name this whatever you want, it will be nil when submitted', :selected => @client.question } %>