如何在Rails中提交布尔参数?

nfm*_*nfm 69 parameters parsing boolean ruby-on-rails

我正在提交一个show_all带有值的参数true.该值与模型无关.

我的控制器将此参数分配给实例变量:

@show_all = params[:show_all]
Run Code Online (Sandbox Code Playgroud)

然而,@show_all.is_a? Stringif @show_all == true总是失败.

Rails解析为布尔值有什么价值?如何明确指定我的参数是布尔值,而不是字符串?

Woj*_*ski 93

更新:Rails 5:

ActiveRecord::Type::Boolean.new.deserialize('0')
Run Code Online (Sandbox Code Playgroud)

更新:Rails 4.2具有以下公共API:

ActiveRecord::Type::Boolean.new.type_cast_from_user("0") # false
Run Code Online (Sandbox Code Playgroud)

以前的答案:

ActiveRecord在https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/column.rb中维护一个真/假表示的列表.

2.0.0-p247 :005 > ActiveRecord::ConnectionAdapters::Column.value_to_boolean("ON")
2.0.0-p247 :006 > ActiveRecord::ConnectionAdapters::Column.value_to_boolean("F")
Run Code Online (Sandbox Code Playgroud)

这不是Rails的公共API的一部分,所以我把它包装成一个帮助方法:

class ApplicationController < ActionController::Base
  private

  def parse_boolean(value)
    ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
  end
end
Run Code Online (Sandbox Code Playgroud)

并添加了一个基本测试:

class ApplicationControllerTest < ActionController::TestCase
  test "parses boolean params" do
    refute ApplicationController.new.send(:parse_boolean, "OFF")
    assert ApplicationController.new.send(:parse_boolean, "T")
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 我们应该注意,`ActiveRecord :: Type :: Boolean.new.type_cast_from_user("0")`将返回如你所提到的`false`,但在Rails 5中它将开始返回true:DEPRECATION警告:你试图分配一个对布尔列没有显式"true"或"false"的值.目前,此值转换为"false".这将改变以匹配Ruby的语义,并将在Rails 5中强制转换为"true".如果您想维护当前行为,则应明确处理要转换为"false"的值. (3认同)
  • `ActiveRecord::Type::Boolean` 只是 `ActiveModel::Type::Boolean` 的别名。使用原始类可能会好一点。 (2认同)

Uģi*_*ols 69

我想评论一下zetetic的答案,但由于我不能这样做,我会发布这个作为答案.

如果你使用

@show_all = params[:show_all] == "1"

然后你可以删除? true : false因为params[:show_all] == "1"语句本身将评估为true或false,因此不需要三元运算符.


ism*_*riv 21

这个问题是比较旧的,但因为我碰到这个问题了几次,并没有像任何提出的解决方案,我砍死自己的东西,它允许使用多个字符串真正的 "上",如"是", ,'t'和假的相反.

猴子修补类String,并添加一个方法将它们转换为布尔值,并/config/initializers按照此处的建议放入此文件:Rails 3中的猴子修补

class String
  def to_bool
    return true if ['true', '1', 'yes', 'on', 't'].include? self
    return false if ['false', '0', 'no', 'off', 'f'].include? self
    return nil
  end
end
Run Code Online (Sandbox Code Playgroud)

请注意,如果该值不是true或false的有效值,则返回nil.搜索?paid=false(返回所有未支付的记录)并不是?paid=(我没有说明是否必须支付 - 所以放弃这个).

然后,按照此示例,控制器中的逻辑将如下所示:

Something.where(:paid => params[:paid].to_bool) unless params[:paid].try(:to_bool).nil?
Run Code Online (Sandbox Code Playgroud)

它非常整洁,有助于保持控制器/模型的清洁.

  • 恭喜你,你现在有一个`String#to_bool`可以返回`nil`.请冥想一段时间,然后将方法重命名为`String#maybe_bool?`或诉诸'ArgumentError`. (17认同)
  • 每次调用此方法时,都会生成至少一个数组.将这些数组移动到冻结常量中.`TRUE_VALUES = ['true'.freeze,'1'.freeze,'yes'.freeze,'on'.freeze,'t'.freeze]`.这a)节省了内存,b)防止了字符串的运行时更改. (5认同)
  • 一个出色的解决方案,干净,整洁,并为String类添加了真正有用的功能.非常好. (2认同)
  • 这可以进一步简化为`def to_bool; ['true','1','yes','on','t'].包括?自; end` (2认同)

zet*_*tic 17

@show_all = params[:show_all] == "1" ? true : false
Run Code Online (Sandbox Code Playgroud)

如果您从复选框传递值,这应该很好地工作 - 哈希中的缺失键生成nil,在条件中计算结果为false.

编辑

正如这里指出的那样,三元运算符不是必需的,所以这可以是:

@show_all = params[:show_all] == "1"