Ruby-on-rails 如何在 Rails 中提交布尔参数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3673607/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 23:11:25  来源:igfitidea点击:

How do I submit a boolean parameter in Rails?

ruby-on-railsparsingparametersboolean

提问by nfm

I'm submitting a parameter show_allwith the value true. This value isn't associated with a model.

我正在提交一个show_all值为的参数true。此值与模型无关。

My controller is assigning this parameter to an instance variable:

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

@show_all = params[:show_all]

However, @show_all.is_a? String, and if @show_all == truealways fails.

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

What values does Rails parse as booleans? How can I explicitly specify that my parameter is a boolean, and not a string?

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

采纳答案by U?is Ozols

I wanted to comment on zetetic answer but as I can't do that yet I'll post this as an answer.

我想对 zetetic 的答案发表评论,但由于我无法做到这一点,因此我会将其发布为答案。

If you use

如果你使用

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

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

then you can drop ? true : falsebecause params[:show_all] == "1"statement itself will evaluate to true or false and thus ternary operator is not needed.

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

回答by Wojtek Kruszewski

UPDATE: Rails 5:

更新:Rails 5:

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

UPDATE: Rails 4.2 has public API for this:

更新:Rails 4.2 为此提供了公共 API:

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

PREVIOUS ANSWER:

以前的答案:

ActiveRecord maintains a list of representations for true/false in https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/column.rb

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

This is not part of Rails' public API, so I wrapped it into a helper method:

这不是 Rails 公共 API 的一部分,所以我将它封装到一个辅助方法中:

class ApplicationController < ActionController::Base
  private

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

and added a basic test:

并添加了一个基本测试:

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

回答by ismriv

This question is rather old, but since I came across this issue a couple of times, and didn't like any of the solutions proposed, I hacked something myself which allows to use multiple strings for truesuch as 'yes', 'on', 't' and the opposite for false.

这个问题很老了,但是由于我遇到过这个问题几次,并且不喜欢提出的任何解决方案,所以我自己破解了一些允许使用多个字符串为真的东西,例如“是”,“开” , 't' 和 false 相反。

Monkey patch the class String, and add a method to convert them to boolean, and put this file in /config/initializersas suggested here: Monkey Patching in Rails 3

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

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

Notice that if the value is none of the valid ones either for true or false, then it returns nil. It's not the same to search for ?paid=false(return all records not paid) than ?paid=(I don't specify if it has to be paid or not -- so discard this).

请注意,如果该值不是 true 或 false 的有效值,则它返回 nil。搜索?paid=false(返回所有未支付的记录)与搜索?paid=(我没有指定是否必须支付 - 所以丢弃它)不同。

Then, following this example, the logic in your controller would look like this:

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

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

It's pretty neat, and helps to keep controllers/models clean.

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

回答by zetetic

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

This should work nicely if you're passing the value in from a checkbox -- a missing key in a hash generates nil, which evaluates to false in a conditional.

如果您从复选框传递值,这应该会很好地工作 - 散列中缺少的键会生成 nil,在条件下评估为 false。

EDIT

编辑

As pointed out here, the ternary operator is not necessary, so this can just be:

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

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

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

回答by benr75

You could change your equality statement to:

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

@show_all == "true"

If you want it to be a boolean you could create a method on the string class to convert a string to a boolean.

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

回答by Jeremy Burton

I think the simplest solution is to test "boolean" parameters against their String representation.

我认为最简单的解决方案是针对它们的字符串表示测试“布尔”参数。

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

Regardless of whether Rails delivers the parameter as the String "true" or "false" or an actual TrueClass or FalseClass, this test will always work.

无论 Rails 将参数作为字符串“true”或“false”还是实际的 TrueClass 或 FalseClass 传递,此测试始终有效。

回答by chaimann

Another approach is to pass only the key without a value. Although using ActiveRecord::Type::Boolean.new.type_cast_from_user(value)is pretty neat, there might be a situation when assigning a value to the param key is redundant.

另一种方法是只传递没有值的键。尽管 usingActiveRecord::Type::Boolean.new.type_cast_from_user(value)非常简洁,但可能存在为 param 键分配值是多余的情况。

Consider the following: On my products index view by default I want to show only scoped collection of products (e.g. those that are in the stock). That is if I want to return all the products, I may send myapp.com/products?show_all=trueand typecast the show_allparameter for a boolean value.

考虑以下事项: 默认情况下,在我的产品索引视图中,我只想显示范围内的产品集合(例如,库存中的产品)。也就是说,如果我想返回所有产品,我可以发送myapp.com/products?show_all=true和类型转换show_all布尔值的参数。

However the opposite option - myapp.com/products?show_all=falsejust makes no sense since it will return the same product collection as myapp.com/productswould have returned.

然而,相反的选项 -myapp.com/products?show_all=false只是没有意义,因为它将返回与返回的相同的产品集合myapp.com/products

An alternative:

替代:

if I want to return the whole unscoped collection, then I send myapp.com/products?alland in my controller define

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

private

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

If the key is present in params, then regardless of its value, I will know that I need to return all products, no need to typecast value.

如果键存在于 params 中,那么无论它的值如何,我都会知道我需要返回所有产品,不需要对值进行类型转换。

回答by mohamed-ibrahim

You can add the following to your model:

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

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

回答by Emad

You could just do

你可以做

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

回答by ecoologic

It's worth noting that if you're passing down a value to an ActiveModelin Rails > 5.2, the simpler solution is to use attribute,

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

class Model
  include ActiveModel::Attributes

  attribute :show_all, :boolean
end

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

As can be seen here.

可以在这里看到。



Before 5.2 I use:

在 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