Rails在ActiveRecord :: Relation Object中查找记录,而无需再次查询数据库

时间:2015-07-08 14:48:21

标签: ruby-on-rails ruby activerecord

我想在ActiveRecord::Relation对象中找到特定记录,以便我可以获取该记录的属性。

以下是有效的,但问题是它使用find_by语句再次访问数据库。它不应该。 rails应该有一种方法可以在ActiveRecord::Relation对象中找到该对象,而不必再次查询数据库。

#returns an ActiveRecord::Relation object
@blogs = Blog.all

# Search for the blog within that ActiveRecord::Relation object, NOT the database
@blogs.find_by(id: 1).title #do this statement but don't hit the database again

4 个答案:

答案 0 :(得分:15)

加载完成后,可以使用常规数组方法。 find实际上是非常有趣的方法 - 如果指定了block,它将被委托给关系目标:

@blogs.find {|b| b.id == 1}

答案 1 :(得分:12)

当你致电find_by时,它会打到数据库。

关系对象用于延迟加载db结果。

all调用加载后,您可以在生成的数组中进行搜索。

如果你想在ruby过程中查看已经存在于内存中的结果,那么你应该使用finddetect(它做同样的事情)来查看数组。我倾向于使用detect,所以很明显它没有访问数据库:

@blogs.detect { |b| b.id == 1 }

http://ruby-doc.org/core-2.2.0/Enumerable.html#method-i-detect

答案 2 :(得分:1)

您可以像这样扩展定义的关联:

class User < AR
  has_many :roles do
    def find_for(params)
      find { |record| params.all? { |key, val| record[key] == val } }
    end
  end
end

User.first.roles.find_for(foo: 'bar', baz: 'word') # => return instance of Role if its #foo equal 'bar' and its #baz equal 'word'

答案 3 :(得分:-2)

您始终可以使用where子句。例如

@blogs.where(id: 1).first.reload

获取(并从数据库重新加载)ID为1的@blog实例。请记住,此查询将快速,高效且安全(如果您要添加params[:id]而不是硬编码ID。