活动记录视图为单个记录方法生成 SQL



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)在语义上是等效的。

最新更新