find、find_by、find_by_xx、where的区别
find
返回一条或多条记录
只能按id查找,即是参数为数字
找不到记录会报错(既然都给到id了,那应该是期望它存在,所以不存在的话,应该raise)
# activerecord-5.0.2/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.include?(inheritance_column) ||
ids.first.kind_of?(Array)
id = ids.first
if ActiveRecord::Base === id
id = id.id
ActiveSupport::Deprecation.warn(<<-MSG.squish)
You are passing an instance of ActiveRecord::Base to `find`.
Please pass the id of the object by calling `.id`.
MSG
end
key = primary_key
statement = cached_find_by_statement(key) { |params|
where(key => params.bind).limit(1)
}
record = statement.execute([id], self, connection).first
unless record
raise RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}",
name, primary_key, id)
end
record
rescue RangeError
raise RecordNotFound.new("Couldn't find #{name} with an out of range value for '#{primary_key}'",
name, primary_key)
end
find_by
也只返回一条记录(first)
参数一般为hash,如{id: 99}
# activerecord-5.0.2/lib/active_record/core.rb
def find_by(*args) # :nodoc:
return super if scope_attributes? || reflect_on_all_aggregations.any?
hash = args.first
return super if !(Hash === hash) || hash.values.any? { |v|
v.nil? || Array === v || Hash === v || Relation === v || Base === v
}
# We can't cache Post.find_by(author: david) ...yet
return super unless hash.keys.all? { |k| columns_hash.has_key?(k.to_s) }
keys = hash.keys
statement = cached_find_by_statement(keys) { |params|
wheres = keys.each_with_object({}) { |param, o|
o[param] = params.bind
}
where(wheres).limit(1)
}
begin
statement.execute(hash.values, self, connection).first
rescue TypeError
raise ActiveRecord::StatementInvalid
rescue RangeError
nil
end
end
find_by!
同find_by,但找不到记录会报错
def find_by!(*args) # :nodoc:
find_by(*args) or raise RecordNotFound.new("Couldn't find #{name}", name)
end
find_by_xx
首次执行会动态定义一个方法名为find_by_xx,方法体为find_by({xx: yy})的方法,即是效果同find_by。其运作如下
where
返回的是ActiveRecord::Relation