ActiveRecord查找开始
真的很简单的问题 – 我如何做一个search查找名称以ActiveRecord中的某个string开始的所有logging。 我已经在互联网上看到了各种各样的字节,使用了逐字的LIKE SQL子句 – 但是从我听说的不是“正确”的方式。
有没有适当的Rails方法?
我强烈推荐使用Searchlogic插件。
然后就像:
@search = Model.new_search(params[:search]) @search.condition.field_starts_with = "prefix" @models = @search.all
Searchlogic非常聪明,就像ActiveRecord一样,在starts_with
条件下select字段名称。 它也将处理所有的分页。
这种方法将有助于防止SQL注入,也将是数据库不可知的。 Searchlogic最终会根据您使用的数据库适配器以不同方式处理search。 你也不必写任何SQL!
Searchlogic有很好的文档,很容易使用(我自己是Ruby和Rails的新手)。 当我被困住了,插件的作者甚至在几个小时内回答了一个直接的电子邮件,帮助我解决了我的问题。 我不能推荐Searchlogic足够…你可以告诉。
如果你正在寻找在数据库中search,那么你需要使用SQL。
当然,您需要在数据库中进行search,否则您需要将所有对象加载到Ruby中(这不是件好事)。
所以,你需要类似的东西
MyModel.find(:all, :conditions => ["field LIKE ?", "#{prefix}%"])
其中prefix
是您正在寻找的string的variables。
在Rails 3.0+中,这成为:
MyModel.where("field LIKE :prefix", prefix: "#{prefix}%")
免责声明:我是Ruby和Rails的新手,我仍然试图学习Ruby的方式来做事,但是我一直在编写我一生中超过一半的时间,并在专业领域工作了十年。 DRY是一个我非常熟悉的概念。 这是我如何实现它。 这与纳尔斯克的回答非常相似,我认为这也是好的。
# name_searchable.rb # mix this into your class using # extend NameSearchable module NameSearchable def search_by_prefix (prefix) self.where("lower(name) LIKE '#{prefix.downcase}%'") end end
然后在你的模型中:
class User < ActiveRecord::Base extend NameSearchable ... end
然后当你想使用它:
User.search_by_prefix('John') #or User.search_by_prefix("#{name_str}")
有一件事要注意:
传统的关系型数据库在满足这种查询方面并不是非常好的。 如果你正在寻找一个高度响应的实现,不会在负载下杀死你的数据库,那么你应该使用一个针对目的而定制的解决scheme。 stream行的例子包括Solr或狮身人面像,还有很多其他的。 通过这个实现,既然你干了,你可以在一个地方用一个单独的索引器replace实现,你就可以准备好了。
非常像上面的答案,但是如果你使用的是ActiveRecord … 2.1或者更高版本,你可以使用一个命名的作用域,它允许你在通过关联检索的logging上使用这个“finder”
class User named_scope :with_name_like, lambda {|str| :conditions => ['lower(name) like ?', %(%#{str.downcase}%)] } end
用于:
User.with_name_like("Samson")
(使用“Samson”这样的名字返回数据库中的所有用户。
要么:
some_association.users.with_name_like("Samson")
用户只能使用“Samson”这个名字。
我不想每次想查看一个特定的列是否以一个前缀开始时写一个范围。
# initializers/active_record_initializers.rb class ActiveRecord::Base # do not accept a column_name from the outside without sanitizing it # as this can be prone to sql injection def self.starts_with(column_name, prefix) where("lower(#{column_name}) like ?", "#{prefix.downcase}%") end end
像这样调用它:
User.starts_with('name', 'ab').limit(1)
现在是2012年,我想我会把这个更新纳入纳尔斯克的答案。
named_scope
变得简单的scope
,所以这个例子变成了
class User scope :name_starts_with, lambda {|str| :conditions => ['lower(name) like ?', "#{str.downcase}%"] } end
注意我从narsk的解决scheme中删除了第一个%
,因为OP要求的是“starts_with”而不是“contains”匹配。
现在你可以做类似的事情了
User.name_starts_with("b").each do {|bs| puts bs.inspect} bob = User.name_starts_with("bob").first … etc
请注意,范围总是返回集合 ,而不是个别的结果。 当我刚刚开始使用AR时,这让我感到不快,我仍然设法忘记了这一切。
戴夫萨格,我想你的代码的第一部分应该是
class User scope :name_starts_with, (lambda do |str| {:conditions => ['lower(name) like ?', "#{str.downcase}%"]} end ) end
对于同样的事情,非常简洁的语法可能是:
Model.where(field: ('prefix'...'prefiy'))
这使得:
WHERE ( field >= 'prefix' AND field < 'prefiy')
这是作为“prefiy”的工作,是第一个string不符合“前缀”前缀。
我不会正常使用它(我会去squeel或ransack代替),但它可以节省你的一天,如果由于某种原因,你必须坚持散列语法的查询…
- accepted_nested_attributes_for儿童关联validation失败
- Rails的ActiveRecord链“哪里”子句没有多个查询?
- 活动logging – 查找在今天之前被创build的logging
- 何时使用save !,请创build! 和update_attributes! 在Rails中?
- Rails:HasManyThroughAssociationNotFoundError
- 非永久ActiveRecord模型属性
- 使用Rails序列化将散列保存到数据库
- has_many,belongs_to在活动logging移动轨道中的关系4
- Rails – validation协会的存在?