Rails Найти запись в ActiveRecord:: Relation Object без запроса базы данных снова

Я хочу найти конкретную запись в объекте ActiveRecord::Relation, чтобы я мог захватить этот атрибут записи.

Ниже показано, но проблема заключается в том, что он снова удаляет базу данных с помощью этого оператора find_by. Это не должно быть. Должен быть способ для рельсов найти этот объект в объекте 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

Ответ 1

После загрузки realtion вы можете использовать обычные методы массива. find - действительно очень интересный метод здесь - если задан блок, он будет делегирован целевому объекту отношения:

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

Ответ 2

Когда вы вызываете find_by, он попадает в базу данных.

Объект отношения используется для ленивой загрузки результатов db.

Как только они будут загружены для вызова all, вы можете выполнить поиск в результирующем массиве.

Если вы хотите просмотреть результаты, уже записанные в вашем рубиновом процессе, вы должны посмотреть в массив с помощью find или detect (которые делают то же самое). Я обычно использую 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'

Ответ 4

Вы всегда можете использовать предложение where. Например,

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

Получить (и перезагрузить из базы данных) экземпляр @blog с идентификатором 1. И имейте в виду, что этот запрос будет быстрым, эффективным и безопасным (в случае, если вы хотите добавить params[:id] вместо жестко запрограммированного ID.