Rails "Where" 方法 - 大于 (">") 使用无限范围
Rails "Where" method - greater than (">") using endless ranges
我最近发现了一个巧妙的技巧来替换 rails where
中的大于/小于,您可以在其中使用范围替换 where:
的字符串版本
Post.where('id <= ?', 10)
可以替换为:
Post.where(id: ..10)
三个点将其从 <=
更改为 <
Post.where('id < ?', 10)
可以替换为:
Post.where(id: ...10)
这个技巧似乎适用于:
- 小于等于
<=
- 小于
<
- 大于等于
>=
但是它不适用于大于 >
因为:
Post.where(id: 10..)
和 Post.where(id: 10...)
都将搜索大于或等于。
我的问题是,有没有一种方法可以让它工作超过(除了用 + 1
破解它?):
Post.where(id: (10+1)..)
我的假设是答案是否定的,但我还是想问!
下面是我所说内容的完整示例:
Post.where(id: ..9)
=> Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" <= [["id", 9]]
Post.where(id: ...9)
=> Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" < [["id", 9]]
Post.where(id: 1..)
=> Post Load (0.4ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" >= [["id", 1]]
# NOTE: THIS STILL ONLY GOES >=, NOT >
Post.where(id: 1...)
=> Post Load (0.4ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" >= [["id", 1]]
您可以使用where.not
Post.where.not(id: ..10).to_sql
# => SELECT "posts".* FROM "posts" WHERE "posts"."id" > 10
Post.where.not(id: ...10).to_sql
# => SELECT "posts".* FROM "posts" WHERE "posts"."id" >= 10
请注意,Post.where(id: (10+1)..)
有效,因为 id
是整数列。但是,这不适用于小数列,例如 Post.where('average_rating > 3.0')
。使用 Post.where(average_rating: (3.0+1)..)
将查找平均评分 > 4 的帖子,但会跳过平均评分为 3.5 的帖子。 Post.where.not(average_rating: ..3.0)
将产生正确的查询。
问题的主要目的是试图避免将长查询更改为“字符串”方法:
# good
Post.where(name: name, type: type, whatever: whatever)
# bad - uses string approach
Post.where('name = :name AND type = :type AND whatever = :whatever',
name: name, type: type, whatever: whatever)
如果大于需要,一种解决此问题并使其可读的方法是将查询拆分为 2 个单独的 where 方法:
# good - only uses string approach with greater than which is more
# readable that where.not
Post.where(name: name, type: type, whatever: whatever).where('id > ?', 10)
# bad - uses string method
Post.where('name = :name AND type = :type AND whatever = :whatever AND id > :id',
name: name, type: type, whatever: whatever, id: 10)
# bad - where.not is not very readable
Post.where(name: name, type: type, whatever: whatever).where.not(id: ..10)
我最近发现了一个巧妙的技巧来替换 rails where
中的大于/小于,您可以在其中使用范围替换 where:
Post.where('id <= ?', 10)
可以替换为:
Post.where(id: ..10)
三个点将其从 <=
更改为 <
Post.where('id < ?', 10)
可以替换为:
Post.where(id: ...10)
这个技巧似乎适用于:
- 小于等于
<=
- 小于
<
- 大于等于
>=
但是它不适用于大于 >
因为:
Post.where(id: 10..)
和 Post.where(id: 10...)
都将搜索大于或等于。
我的问题是,有没有一种方法可以让它工作超过(除了用 + 1
破解它?):
Post.where(id: (10+1)..)
我的假设是答案是否定的,但我还是想问!
下面是我所说内容的完整示例:
Post.where(id: ..9)
=> Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" <= [["id", 9]]
Post.where(id: ...9)
=> Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" < [["id", 9]]
Post.where(id: 1..)
=> Post Load (0.4ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" >= [["id", 1]]
# NOTE: THIS STILL ONLY GOES >=, NOT >
Post.where(id: 1...)
=> Post Load (0.4ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" >= [["id", 1]]
您可以使用where.not
Post.where.not(id: ..10).to_sql
# => SELECT "posts".* FROM "posts" WHERE "posts"."id" > 10
Post.where.not(id: ...10).to_sql
# => SELECT "posts".* FROM "posts" WHERE "posts"."id" >= 10
请注意,Post.where(id: (10+1)..)
有效,因为 id
是整数列。但是,这不适用于小数列,例如 Post.where('average_rating > 3.0')
。使用 Post.where(average_rating: (3.0+1)..)
将查找平均评分 > 4 的帖子,但会跳过平均评分为 3.5 的帖子。 Post.where.not(average_rating: ..3.0)
将产生正确的查询。
问题的主要目的是试图避免将长查询更改为“字符串”方法:
# good
Post.where(name: name, type: type, whatever: whatever)
# bad - uses string approach
Post.where('name = :name AND type = :type AND whatever = :whatever',
name: name, type: type, whatever: whatever)
如果大于需要,一种解决此问题并使其可读的方法是将查询拆分为 2 个单独的 where 方法:
# good - only uses string approach with greater than which is more
# readable that where.not
Post.where(name: name, type: type, whatever: whatever).where('id > ?', 10)
# bad - uses string method
Post.where('name = :name AND type = :type AND whatever = :whatever AND id > :id',
name: name, type: type, whatever: whatever, id: 10)
# bad - where.not is not very readable
Post.where(name: name, type: type, whatever: whatever).where.not(id: ..10)