【问题标题】:NoMethodError - undefined method `where_values' | Upgraded from rails 4.2 to 5.0.1NoMethodError - 未定义的方法`where_values' |从 rails 4.2 升级到 5.0.1
【发布时间】:2021-06-22 12:32:30
【问题描述】:

我最近使用 ruby​​ 2.4.5 将我的 rails 应用程序从 4.2.8 升级到 5.0.1 遇到这个错误

NoMethodError - 未定义的方法 `where_values'

查询:

PlacementActivityStep.where(query_values_hash[:query_string], query_values_hash[:values]) .where_values.select{|x| x.present?}

如何使用 where_clause 在 rails 5.0.1 中实现相同的查询,因为 where_values 已从新的 rails 版本中删除? 参考:Ruby on Rails where_values method

【问题讨论】:

  • 您链接到的其他问题的答案有什么不清楚的地方吗?
  • PlacementActivityStep.where(query_values_hash[:query_string], query_values_hash[:values]) .where_clause.select{|x| x.present?} 给出 NoMethodError - 调用 #<:relation::whereclause:0x000055f5501f8f10> 的私有方法 `select'。现在该怎么办?
  • where_values_hash 能解决问题吗?
  • 没有。 where_values_hash 返回哈希,而 where_values 返回 <:nodes::equality: where_clause arel ::attributes::attribute ...>

标签: ruby-on-rails ruby activerecord where-clause


【解决方案1】:

以下测试在Rails 5.2.2
首先,where_values 不打算供公众使用,请参阅https://bugs.ruby-lang.org/issues/12962
要获得相同的行为,您必须做一些技巧。

我不知道你会使用生成的 arel 代码做什么,如果条件复杂,我更喜欢直接使用 arel 来创建条件。而且你会失去一些自动类型检测。

考虑一下(不好的例子,但只是为了说明区别):

# model Foo have column 'bar' that is sql type string
Foo.where('bar = :one OR bar = :two', one: 55, two: nil ).to_sql
=> "SELECT `foos`.* FROM `foos` WHERE (firstname = 55 OR firstname = NULL)"
# bad, the last should be "firstname IS NULL"

# use Rails "magic"
Foo.where(bar: [ 55, nil ]).to_sql
=> "SELECT `foos`.* FROM `foos` WHERE (`foos`.`firstname` = '55' OR `foos`.`firstname` IS NULL)"
# "`firstname` IS NULL" as it should be (and '55' is a string)

# if it is the arel you want, you can use it directly
fo_a = Foo.arel_table
fo_a[:bar].eq_any([ 55, nil ]).to_sql
=> "(`foos`.`firstname` = '55' OR `foos`.`firstname` IS NULL)"

# that is the same as if you where using this in Rails 4:
Foo.where(bar: [ 55, nil ]).where_values.first.to_sql

# even if you use a hackish way you will not get the same result
Foo.where(bar: [ 55, nil ]).where_clause.send(:predicates).first.to_sql
=> "(`foos`.`firstname` = ? OR `foos`.`firstname` IS NULL)"
# '55' is gone (it's a "bind value")

【讨论】:

    猜你喜欢
    • 2015-10-21
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 2017-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多