Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How a chaining interface like Rails ActiveRecord is built?

I'm intrigued. How User.where(name: 'Foo').where(age: 20) works with only one database call?

Does the method where know if it is the last of the chain and change its behavior? And if so, how that can be done?

like image 566
Cassiano Franco Avatar asked Nov 30 '25 02:11

Cassiano Franco


1 Answers

It returns self after each time it adds the query to its internal query builder.

where doesn't necessarily know where it's at; ActiveRecord waits for itself to be enumerated on before even querying the database. Example:

users = User.where(active: true)
users.loaded? # false 
users.each { }
users.loaded? # true 

each, map, first, last, etc. all will trigger the query to be loaded.

Here's an example of a super-naive query builder:

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
like image 171
Josh Brody Avatar answered Dec 02 '25 17:12

Josh Brody



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!