像 Rails ActiveRecord 这样的链接接口是如何构建的?

Cas*_*nco 3 ruby ruby-on-rails rails-activerecord

我很好奇。User.where(name: 'Foo').where(age: 20)仅使用一个数据库调用如何工作?

该方法是否where知道它是否是链的最后一个并改变其行为?如果是这样,如何做到这一点?

Jos*_*ody 5

self每次将查询添加到其内部查询构建器后,它都会返回。

where不一定知道它在哪里;ActiveRecord 甚至在查询数据库之前等待自身被枚举。例子:

users = User.where(active: true)
users.loaded? # false 
users.each { }
users.loaded? # true 
Run Code Online (Sandbox Code Playgroud)

eachmapfirstlast等都将触发要加载的查询。

这是一个超级幼稚的查询构建器的示例:

class FakeRecord
  include Enumerable
  def self.all_args
    @all_args ||= []
  end

  def self.where(*args)
    all_args << args 
    self
  end

  def self.each
    puts "Executing sql #{all_args.join(", ")}"
    yield [1, 2, 3]
  end
end

FakeRecord.where(potato: true).where(dinosaur: false).each do |thing|
  puts thing
end
Run Code Online (Sandbox Code Playgroud)