【问题标题】:How to user instance method in where query inside scope如何在范围内查询的地方使用实例方法
【发布时间】:2022-12-11 11:26:57
【问题描述】:

我在用户模型中定义了一个实例方法。我想在范围内使用该实例方法,但我不确定该怎么做。请帮我找到我要去哪里错了。

用户.rb

has_many :users_availables
has_many :availables, through: :users_availables

scope :under_2500_value, -> { joins(:available).where('(value * availables.count / 100) in (?)', 0..2499) }
scope :under_5000_value, -> { joins(:availables).where('(value * availables.count / 100) in (?)', 2500..4999) }

def current_value
  value * available.count / 100
end

available 是另一个与用户表有关系的表,如下所示。

在 Rails 控制台中,如果我尝试以下命令,它会返回 current_value 为 7500 的用户,但它应该在 2500 之间返回。

User.under_2500_value

请帮我找到我要去哪里错了。

User.under_2500_value 的结果

irb(main):033:0> User.under_2500_value.to_sql
=> "SELECT \"users\".* FROM \"users\" INNER JOIN \"users_availables\" ON \"users_availables\".\"user_id\" = \"users\".\"id\" INNER JOIN \"availables\" ON \"availables\".\"id\" = \"users_availables\".\"available_id\" WHERE ((value * availables.count / 100) in (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334......,2497,2498,2499))"

【问题讨论】:

  • 可以贴一下User.under_2500_value.to_sql的结果吗
  • @Chiperific 请检查问题,我已经发布了 User.under_2500_value.to_sql 的结果
  • @spickermann 对你很好,因为您的范围不匹配:“你的两个范围不匹配,第一个有连接(:可用),另一个有连接(:可用)”。他写了他的答案来反映你展示的代码。
  • @Chiperific 是的,他很善良

标签: ruby-on-rails ruby activerecord ruby-on-rails-5


【解决方案1】:

available.count是一个Ruby方法,需要先翻译成SQL。例如,JOINGROUP BYCOUNT 的组合

此外,value * availables.count / 100 之类的表达式可能会导致浮点结果,具体取决于输入的类型。

让我们想象一个像25.5这样的值被返回。那么 Ruby 表达式 (1..100).cover?(25.5) 将是 true。但是当将一个范围传递给 SQL 时,它的工作方式有点不同,并被转换成一个整数数组(只需查看问题中生成的 SQL 查询的末尾):

=> "SELECT [...] FROM [...] WHERE ((value * availables.count / 100) in (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334......,2497,2498,2499))"

该数组显然不包含任何浮点数,如25.5

为了解决您的问题,我会将上述 SQL 运算符与 BETWEEN 运算符而不是 IN 结合起来:

scope :under_2500_value, -> { 
  joins(:availables).group(:id)
    .having('(value * COUNT(availables) / 100) BETWEEN ? AND ?', 0, 2499) 
}
scope :under_5000_value, -> { 
  joins(:availables).group(:id)
    .having('(value * COUNT(availables) / 100) BETWEEN ? AND ?', 2500, 4999) 
}

【讨论】:

  • 你的两个范围不匹配,第一个有 joins(:available),另一个有 joins(:availables),第一个返回 ActiveRecord::StatementInvalid,第二个返回 current_value 超过 7500 的用户记录,但它应该有返回2500-4999之间
  • @user12763413 我更新了我的答案以解决您的评论。
  • availables 表中的 count 字段呢?你不再使用它了
  • 您的问题实际上不清楚 available.count 是什么。您问题中的代码仅定义了 has_many :availables(复数),availables.count 将返回可用的数量。如果available(单数)是不同的,而count不是可用的数量,而是单个可用的属性,那么您需要在您的问题中澄清这一点。查看您的数据库模式也可​​能有帮助。
  • 谢谢你,先生。下次我会清楚我的问题
猜你喜欢
  • 1970-01-01
  • 2020-06-14
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 2014-03-12
  • 1970-01-01
  • 2011-08-22
  • 2022-12-11
相关资源
最近更新 更多