ActiveRecord 允许您查看为集合生成的 SQL:
User.all.to_sql
如何返回为返回单个记录的方法生成的 SQL?
User.find(1).to_sql # not valid
User.print_sql.find(1) # something like this?
User.where(id: 1).limit(1).to_sql
这就是使用find_by
时在SQL中运行的本质上的内容。
为查找查询生成的 sql,即User.find(1)
SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1],
["LIMIT", 1]]
to_sql
方法是在ActiveRecord::Relation
类中定义的,所以你最好使用
User.where(id: 1).to_sql
=> "SELECT "users".* FROM "users" WHERE "users"."id" = 1"
更新
好的,让我们转向 Rails 6 源代码。这是活动记录 gem 文件的摘录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)
然后从返回ActiveRecord::Relation
集合的first
元素中获取结果。
find_by
方法采用的方法与稍后在同一文件中看到的方法相同。
因此,User.find(1)
和User.where(id: 1).limit(1)
在语义上是等效的。