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

时间:2010-09-09 03:39:07

标签: ruby-on-rails parsing parameters boolean

我提交的参数show_all的值为true。该值与模型无关。

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

@show_all = params[:show_all]

但是,@show_all.is_a? Stringif @show_all == true始终失败。

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

12 个答案:

答案 0 :(得分:87)

更新:Rails 5:

ActiveRecord::Type::Boolean.new.deserialize('0')

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

ActiveRecord::Type::Boolean.new.type_cast_from_user("0") # false

以前的答案:

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")

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

class ApplicationController < ActionController::Base
  private

  def parse_boolean(value)
    ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
  end
end

并添加了基本测试:

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

答案 1 :(得分:67)

我想对zetetic回答发表评论,但由于我不能这样做,我会发布这个作为答案。

如果您使用

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

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

答案 2 :(得分:21)

这个问题相当陈旧,但由于我偶然遇到过这个问题,而且并不喜欢任何提出的解决方案,我自己攻击了一些允许使用多个字符串 true < / strong>例如&#39; yes&#39;,&#39; on&#39;,&#39; t&#39;与错误相反。

Monkey修补类String,并添加一个方法将它们转换为boolean,并按照此处的建议将此文件放在/config/initializers中:Monkey Patching in 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

请注意,如果值为true或false的有效值,则返回nil。搜索?paid=false(返回所有未支付的记录)与?paid=不一样(我没有说明是否需要付费 - 所以请放弃此)。

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

Something.where(:paid => params[:paid].to_bool) unless params[:paid].try(:to_bool).nil?

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

答案 3 :(得分:17)

@show_all = params[:show_all] == "1" ? true : false

如果您从复选框传递值,这应该可以正常工作 - 哈希中缺少的键生成nil,在条件中计算结果为false。

修改

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

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

答案 4 :(得分:4)

您可以将等式声明更改为:

@show_all == "true"

如果您希望它是一个布尔值,您可以在字符串类上创建一个方法,将字符串转换为布尔值。

答案 5 :(得分:3)

我认为最简单的解决方案是针对其String表示测试“boolean”参数。

@show_all = params[:show_all]
if @show_all.to_s == "true"
   # do stuff
end

无论Rails是以字符串“true”还是“false”或实际TrueClass或FalseClass的形式提供参数,此测试都将始终有效。

答案 6 :(得分:1)

你可以做

@show_all = params[:show_all].downcase == 'true'

答案 7 :(得分:0)

您可以将所有布尔参数转换为真正的布尔值,如下所示:

%w(show_all, show_featured).each do |bool_param|
  params[bool_param.to_sym] = params[bool_param.to_sym] == "true"
end

在此解决方案中,nil参数将变​​为false。

答案 8 :(得分:0)

另一种方法是仅传递没有值的键。尽管使用ActiveRecord::Type::Boolean.new.type_cast_from_user(value)非常简洁,但是在为param键分配值时可能存在冗余。

请考虑以下事项: 在我的产品索引视图中,我默认只显示范围的产品集合(例如股票中的那些)。也就是说,如果我想返回所有产品,我可以发送myapp.com/products?show_all=true并对show_all参数进行类型转换以获得布尔值。

然而相反的选项 - myapp.com/products?show_all=false没有任何意义,因为它会返回与myapp.com/products返回的相同的产品系列。

替代方案:

如果我想返回整个未编组的集合,那么我发送myapp.com/products?all并在我的控制器中定义

private

def show_all?
  params.key?(:all)
end

如果密钥存在于params中,那么无论其值如何,我都知道我需要返回所有产品,而不需要强制转换值。

答案 9 :(得分:0)

您可以将以下内容添加到模型中:

def show_all= value
  @show_all = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
end

答案 10 :(得分:0)

值得注意的是,如果要在Rails> 5.2中将值传递给 ActiveModel ,更简单的解决方案是使用attribute

class Model
  include ActiveModel::Attributes

  attribute :show_all, :boolean
end

Model.new(show_all: '0').show_all # => false

可以看到here


在5.2之前,我使用:

class Model
  include ActiveModel::Attributes

  attribute_reader :show_all

  def show_all=(value)
    @show_all = ActiveModel::Type::Boolean.new.cast(value)
  end
end

Model.new(show_all: '0').show_all # => false

答案 11 :(得分:0)

虽然没有明确问题是关于什么的,但我觉得这是适当的相关;如果您尝试在 rails 测试中传递真正的布尔变量,那么您将需要以下语法。

post :update, params: { id: user.id }, body: { attribute: true }.to_json, as: :json

我来到这个线程就是为了寻找这个语法,所以我希望它也能帮助那些寻找这个的人。归功于Lukom