应用范围进行过滤时的异常行为

时间:2019-06-03 09:39:37

标签: ruby-on-rails forms ruby-on-rails-4 rubygems scopes

我有一个型号为CoffeeShop的“ wifi_restrictions”列-一个整数值,表示可以使用wifi的小时数。

我正在使用合并范围内的gem,因此如果我在params中获得的值为“ 0”,则它将返回其中wifi_restrictions = 0的CoffeeShop的所有实例。

我尝试了两种方法来实现此目的。

方法1:

在我的表格中,我有以下内容:

<input type="checkbox" name="no_wifi_restrictions" value="0">

在我的模型中,我有:

scope :wifi_restrictions, -> hours { where(wifi_restrictions: hours) }

在我的控制器中:

has_scope :wifi_restrictions, type: :integer

结果:未定义的方法“任何?”为nil:NilClass

(即使没有提供要过滤的范围的参数,我也无法理解。)


方法2:

在这种方法中,我尝试定义一个新的范围“ no_wifi_restrictions”。

在我的表格中,我有以下内容:

<input type="checkbox" name="no_wifi_restrictions" value="true">

型号:

scope :no_wifi_restrictions, -> { where(wifi_restrictions: 0) }

控制器:

has_scope :no_wifi_restrictions, type: :boolean

结果: 当值是“ true”(no_wifi_restrictions = true)时,这将正确过滤,但是当值是“ false”(no_wifi_restrictions = false)时,将返回所有实例。 在控制台中,如果我搜索CoffeeShop.no_wifi_restrictions,则会正确过滤。但是,如果我搜索CoffeeShop.where(no_wifi_restrictions:true)或CoffeeShop.where(no_wifi_restrictions:false),那么我都不会返回任何实例。因此,我不确定它甚至在50%的时间内是如何工作的(而且我不确定如何调查幕后情况)。

2 个答案:

答案 0 :(得分:0)

以下行将不起作用:

CoffeeShop.where(no_wifi_restrictions: true)
CoffeeShop.where(no_wifi_restrictions: false)

这些行正在尝试获取no_wifi_restrictions列为true或false的所有CoffeeShop,而我猜Coffeeshops没有该列。

如果参数值为true,则您希望范围返回wifi_restrictions = 0的所有CoffeeShop,否则它将返回wifi_restrictions> 0的所有CoffeeShop。

也许为wifi限制添加一个布尔列也更容易。看起来您正在尝试将布尔值与整数进行比较。

答案 1 :(得分:0)

好的,所以我在想以下内容实际上会在调用有范围方法时将整数值转换为布尔值。

:no_wifi_restrictions, ->{ where(wifi_restrictions: 0) }

所以我认为好吧,如果我发送参数no_wifi_restrictions = true,它将返回所有CoffeeShop实例,如果我在控制台中进行搜索,现在将返回所有实例:

CoffeeShop.no_wifi_restrictions.

但是,这不是它的工作方式。因为在我的参数中,它传递了一个值。因此,当我尝试使用“ true”参数时,我得到:

wrong number of arguments (given 1, expected 0)

我找到的解决方案如下:

scope :no_wifi_restrictions, -> hours { where(wifi_restrictions: hours) }

也可以这样写:

scope :no_wifi_restrictions, -> hours { where("wifi_restrictions = ?", hours) }

这是为了允许将参数传递给作用域(小时)。因此,在这种情况下,我以参数形式将值传递为“ 0”,它将运行以下命令:

CoffeeShop.where(wifi_restrictions: 0)

从本质上来说,“小时”值对于我的需求而言是不必要的,因为我真的不需要或不需要一个参数,只是我必须在params中提供一个值(除非我弄错了,我也已经尝试过删除value属性,但这会导致默认值为“ on”。

因此,即使传递的参数本质上是多余的,以下内容也将起作用:

scope :no_wifi_restrictions, -> hours { where("wifi_restrictions = 0", hours) }

在这种情况下,我真的可以在参数中给出任何值,例如:

value="this_is_a_useless_param"

...并且它仍然可以工作,因为它所需要的只是将参数传递给范围。

也许有人知道实现这一目标的更巧妙的方法,但是现在这对我有用。