用不区分大小写的查找器替换where(username:usernames)

时间:2014-04-29 17:46:51

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

我以前使用where(username: usernames)获取一组用户名,并返回一个ActiveRecord :: Users用户。我已经创建了一个较低的(用户名)索引,并用以下内容替换了User#find_by_username:

def self.find_by_username(username)
  where("lower(username) = ?", username.downcase).first
end

这失败了:

def self.find_by_usernames(usernames)
  where("lower(username) = ?", usernames.map(&:downcase))
end

当它是一个用户名的数组时,它可以工作,但不适用于多个用户名。它生成类似"SELECT \"users\".* FROM \"users\" WHERE (lower(username) = 'joshsmith','vendiddy')"

的SQL

2 个答案:

答案 0 :(得分:3)

更新您的方法如下:

def self.find_by_usernames(usernames)
  where("lower(username) in (?)", usernames.map(&:downcase))
end

使用in代替=,因为您要检查数组中的多个值。

答案 1 :(得分:0)

默认情况下,某些数据库在文本比较时没有区分大小写,例如MySQL。

where("username in (?)", usernames.map(&:downcase))

除非已覆盖默认值,否则上述内容会在MySQL上提供所需的结果。见this post on Stackoverflow

我同意,除非您希望获得较小的速度优势,否则添加较低的函数应该是首选方法,因为数据库服务器不必首先转换字符串。

> Contact.first
Contact Load (172.3ms)  SELECT `contacts`.* FROM `contacts` ORDER BY `contacts`.`id` ASC LIMIT 1
=> #<Contact id: 1, name: "John"> 

> Contact.where(name: "john")
Contact Load (171.9ms)  SELECT `contacts`.* FROM `contacts` WHERE `contacts`.`name` = 'john'
=> #<ActiveRecord::Relation [#<Contact id: 1, name: "John"]> 

> Contact.where(name: "JOHN")
Contact Load (172.3ms)  SELECT `contacts`.* FROM `contacts` WHERE `contacts`.`name` = 'JOHN'
=> #<ActiveRecord::Relation [#<Contact id: 1, name: "John"]>