Представление ActiveRecord, сгенерированное SQL для отдельных методов записи - PullRequest
0 голосов
/ 03 февраля 2020

ActiveRecord позволяет увидеть SQL, сгенерированный для коллекции:

User.all.to_sql

Как я могу вернуть SQL, сгенерированный для метода, который возвращает одну запись?

User.find(1).to_sql # not valid
User.print_sql.find(1) # something like this?

Ответы [ 2 ]

0 голосов
/ 06 февраля 2020

User.where(id: 1).limit(1).to_sql

По сути, это то, что запускается в SQL при использовании find_by.

sql, сгенерированный для запроса поиска, ie User.find(1) это

SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], 
["LIMIT", 1]]
0 голосов
/ 04 февраля 2020

to_sql метод определен в классе ActiveRecord::Relation, поэтому вам лучше использовать

User.where(id: 1).to_sql
 => "SELECT \"users\".* FROM \"users\" WHERE \"users\".\"id\" = 1"

ОБНОВЛЕНИЕ

Хорошо, давайте обратимся к Rails 6 источник. Вот выдержка из файла gem ActiveRecord activerecord/lib/active_record/core.rb

def find(*ids) # :nodoc:
  # We don't have cache keys for this stuff yet
  return super unless ids.length == 1
  return super if block_given? ||
                  primary_key.nil? ||
                  scope_attributes? ||
                  columns_hash.key?(inheritance_column) && !base_class?

  id = ids.first

  return super if StatementCache.unsupported_value?(id)

  key = primary_key

  statement = cached_find_by_statement(key) { |params|
    where(key => params.bind).limit(1)
  }

  record = statement.execute([id], connection)&.first
  unless record
    raise RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id)
  end
  record
end

Хорошо видно, что метод find расширен до where(primary_key => id).limit(1), а затем результат взят из first элемент возвращенного ActiveRecord::Relation collection.

find_by метод использует тот же подход, который можно увидеть позже в том же файле.

Таким образом, User.find(1) и User.where(id: 1).limit(1) семантически эквивалентны .

...