我的产品型号包含一些项目

 Product.first
 => #<Product id: 10, name: "Blue jeans" >

我现在从另一个数据集导入一些产品参数,但是名称的拼写不一致。例如,在另一个数据集中,Blue jeans可以拼写为Blue jeans。

我想要产品。find_or_create_by_name("Blue Jeans"),但这将创建一个与第一个几乎相同的新产品。我的选择是什么,如果我想找到和比较小写的名字。

性能问题在这里并不重要:只有100-200个产品,我希望将其作为导入数据的迁移来运行。

什么好主意吗?


当前回答

类似于安德鲁斯的第一条:

对我有用的是:

name = "Blue Jeans"
Product.find_by("lower(name) = ?", name.downcase)

这样就不需要在同一个查询中执行#where和#first。希望这能有所帮助!

其他回答

另一种没有人提到的方法是在ActiveRecord::Base中添加不区分大小写的查找器。详情可以在这里找到。这种方法的优点是不必修改每个模型,也不必向所有不区分大小写的查询添加lower()子句,只需使用不同的查找器方法即可。

在postgres:

 user = User.find(:first, :conditions => ['username ~* ?', "regedarek"])

另一种选择是

c = Product.find_by("LOWER(name)= ?", name.downcase)

Find_or_create现在已弃用,你应该使用一个AR关系来代替加上first_or_create,如下所示:

TombolaEntry.where("lower(name) = ?", self.name.downcase).first_or_create(name: self.name)

这将返回第一个匹配的对象,如果不存在,则为您创建一个。

这是Rails中的一个完整设置,供我自己参考。如果这对你也有帮助,我很高兴。

查询:

Product.where("lower(name) = ?", name.downcase).first

验证器:

validates :name, presence: true, uniqueness: {case_sensitive: false}

索引(答案来自Rails/ActiveRecord中不区分大小写的唯一索引?):

execute "CREATE UNIQUE INDEX index_products_on_lower_name ON products USING btree (lower(name));"

我希望有一种更漂亮的方式来完成第一个和最后一个,但话又说回来,Rails和ActiveRecord是开源的,我们不应该抱怨——我们可以自己实现它并发送pull request。