【问题标题】:Rails Find a Record Within ActiveRecord::Relation Object without querying database againRails 在 ActiveRecord::Relation 对象中查找记录而无需再次查询数据库
【发布时间】:2015-07-08 14:48:21
【问题描述】:

我想在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

【问题讨论】:

    标签: ruby-on-rails ruby activerecord


    【解决方案1】:

    加载关系后,您可以使用常规数组方法。 find 这里其实是一个很有意思的方法——如果指定了block,就会委托给relation target:

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

    【讨论】:

      【解决方案2】:

      当你调用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

      【讨论】:

        【解决方案3】:

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

        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'
        

        【讨论】:

        • 我真的不敢相信这是解决我特定用例的答案。谢谢@ka8725
        【解决方案4】:

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

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

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

        【讨论】:

        • 使用 ActiveRecord 的where 方法导致数据库查询。
        • 这将导致数据库查询。 OP 不希望这样。
        猜你喜欢
        • 1970-01-01
        • 2016-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多