Takarik::Data::QueryBuilder(T)
Constants
Rails compatibility constants
Constructors
Class methods
Instance methods
Calculate the average of values in the specified column. Returns the average as a number (possibly a floating-point number). Returns nil if no records match the query or if all values are NULL.
Examples: Order.average("subtotal") # => 25.125 Order.where(status: "shipped").average("subtotal") # => 29.83
SQL: SELECT AVG(subtotal) FROM orders SQL: SELECT AVG(subtotal) FROM orders WHERE (orders.status = 'shipped')
Count records by a specific column, counting only non-null values. This is useful for counting records that have a value present in a specific field.
Examples: Customer.count(:title) # => 3 (only customers with a title) Customer.where(active: true).count(:email) # => 5 (active customers with email)
SQL: SELECT COUNT(title) FROM customers SQL: SELECT COUNT(email) FROM customers WHERE (customers.active = 1)
Count records in the current relation. Returns the number of records matching the current query conditions.
Examples: Customer.count # => 5 Customer.where(first_name: 'Ryan').count # => 2 Customer.group(:status).count # => {"active" => 3, "inactive" => 2}
SQL: SELECT COUNT() FROM customers SQL: SELECT COUNT() FROM customers WHERE (customers.first_name = 'Ryan')
Set default attributes that will be used when creating new records. These attributes are only applied when creating new records, not when finding existing ones.
Examples: Customer.create_with(locked: false).find_or_create_by(first_name: "Andy") User.create_with(active: true, role: "user").find_or_create_by(email: "test@example.com")
The create_with attributes are merged with the find_or_create_by conditions when creating.
Run EXPLAIN on the current relation to analyze query execution plan. EXPLAIN output varies for each database adapter.
Examples: Customer.where(id: 1).joins(:orders).explain Customer.where(id: 1).includes(:orders).explain User.where("age > 21").explain(:analyze, :verbose) # PostgreSQL options Order.joins(:customer).explain(:analyze) # MySQL/MariaDB options
For databases that support it (PostgreSQL, MySQL, MariaDB), you can pass options: :analyze - Actually execute the query and show real execution statistics :verbose - Show additional details about the query plan :buffers - Show buffer usage information (PostgreSQL) :costs - Show cost estimates (PostgreSQL, default: true) :format - Output format: :text, :json, :xml, :yaml (PostgreSQL)
The method executes the query when using includes() since eager loading may trigger multiple queries, and some queries need results from previous ones.
Retrieve records in batches and yield each one to the block. This is efficient for processing large datasets without loading everything into memory. Uses cursor-based batching for better performance than OFFSET-based batching.
Examples: User.where(active: true).find_each do |user| process_user(user) end
User.find_each(start: 2000, batch_size: 5000) do |user| UserMailer.newsletter(user).deliver_now end
Composite key ordering
Order.find_each(order: [:asc, :desc]) do |order| process_order(order) end
Options: :start - Starting cursor value (inclusive) :finish - Ending cursor value (inclusive) :batch_size - Number of records per batch (default: 1000) :error_on_ignore - Raise error if existing order is present (default: nil) :cursor - Column(s) to use for batching (default: primary_key) :order - Cursor order (:asc/:desc or array like [:asc, :desc], default: :asc)
Returns an Enumerator when no block is given
Yields each batch of records as an array. Uses cursor-based batching for better performance.
Examples: User.find_in_batches do |batch| batch.each { |user| process_user(user) } end
User.find_in_batches(start: 1000, batch_size: 500) do |batch| batch.each { |user| user.update_status } end
Options: Same as find_each - start, finish, batch_size, error_on_ignore, cursor, order
Returns an Enumerator when no block is given
Find the first record matching the current query conditions or create a new one. Uses any create_with attributes when creating new records.
Examples: User.where(active: true).find_or_create_by(name: "Andy") User.create_with(role: "user").find_or_create_by(email: "test@example.com")
Find up to the specified number of records with ordering preserved from query.
Find up to the specified number of records with ordering. Raises RecordNotFound if no records found.
Pluck all the IDs for the relation using the table's primary key. This is a convenience method equivalent to pluck(primary_key).
Examples: Customer.ids # => [1, 2, 3] Customer.where(active: true).ids # => [1, 3]
Yields QueryBuilder objects to work with a batch of records. This is similar to Rails' in_batches method.
Examples: User.where("age > 21").in_batches do |relation| relation.delete_all sleep(1) # Throttle the delete queries end
User.in_batches.each_with_index do |relation, batch_index| puts "Processing relation ##{batch_index}" relation.delete_all end
Options: :of - Specifies the size of the batch (default: 1000) :load - Specifies if the relation should be loaded (default: false) :start - Starting cursor value (inclusive) :finish - Ending cursor value (inclusive) :error_on_ignore - Raise error if existing order is present (default: nil) :cursor - Column(s) to use for batching (default: primary_key) :order - Cursor order (:asc/:desc or array, default: :asc) :use_ranges - Use range iteration for better performance (default: nil, auto-detected)
Returns a BatchEnumerator when no block is given
Simple flexible signature that can handle any nested structure
Rails-compatible joins method that supports multiple associations and nested joins Examples: User.joins(:posts) # Single association User.joins(:posts, :account) # Multiple associations User.joins(posts: [:comments]) # Nested joins User.joins("LEFT JOIN bookmarks ON ...") # Custom SQL Author.joins(books: [{ reviews: { customer: :orders } }, :supplier]) # Complex nested
Find up to the specified number of records in reverse order. Raises RecordNotFound if no records found.
Adds a locking clause to the query for pessimistic locking. This is useful for preventing race conditions when updating records.
Examples: User.lock.first # SELECT * FROM users LIMIT 1 FOR UPDATE User.lock("LOCK IN SHARE MODE").first # SELECT * FROM users LIMIT 1 LOCK IN SHARE MODE User.where(active: true).lock.to_a # SELECT * FROM users WHERE active = 1 FOR UPDATE
The lock is automatically released when the transaction completes. It's recommended to wrap locked queries in a transaction:
User.transaction do user = User.lock.first user.update(name: "New Name") end
Check if there are more than one record matching the current query. Uses an optimized approach with LIMIT 2 to avoid counting all records.
Examples: Order.many? # => true if there are 2 or more orders Order.shipped.many? # => true if there are 2 or more shipped orders Book.where(out_of_print: true).many? # => true if there are 2 or more out of print books
Find the maximum value in the specified column. Returns the maximum value with the corresponding data type. Returns nil if no records match the query or if all values are NULL.
Examples: Order.maximum("subtotal") # => 199.99 Order.where(status: "shipped").maximum("created_at") # => 2023-12-31 23:59:59
SQL: SELECT MAX(subtotal) FROM orders SQL: SELECT MAX(created_at) FROM orders WHERE (orders.status = 'shipped')
Merge another relation's conditions, replacing existing ones where they conflict This is useful for overriding conditions from scopes or previous where clauses
Examples: Book.in_print.merge(Book.out_of_print) # out_of_print condition wins User.where(active: true).merge(User.where(active: false)) # active: false wins
The merge method replaces conflicting conditions rather than adding them with AND
Find the minimum value in the specified column. Returns the minimum value with the corresponding data type. Returns nil if no records match the query or if all values are NULL.
Examples: Order.minimum("subtotal") # => 5.99 Order.where(status: "shipped").minimum("created_at") # => 2023-01-15 10:30:00
SQL: SELECT MIN(subtotal) FROM orders SQL: SELECT MIN(created_at) FROM orders WHERE (orders.status = 'shipped')
Order with string column and optional direction
Order with hash parameter (for nested table ordering like books: { print_year: :desc })
Order with mixed arguments (symbol + hash) - special case
Pick the value(s) from the named column(s) in the current relation. Returns the first row of the specified column values with corresponding data type. This is a short-hand for relation.limit(1).pluck(*column_names).first.
Examples: Customer.where(id: 1).pick(:id) # => 1 Customer.where(id: 1).pick(:id, :first_name) # => [1, "David"] Customer.where(id: 999).pick(:id) # => nil
Execute a custom SQL query and return raw results as an array of hashes. This is similar to find_by_sql but returns raw data instead of model instances. This method is equivalent to Rails' lease_connection.select_all.
Examples: Customer.select_all("SELECT first_name, created_at FROM customers WHERE id = '1'")
=> [{"first_name" => "Rafael", "created_at" => "2012-11-10 23:23:45.281189"}]
The method always returns an array of hashes, even if the query returns a single record. Returns an empty array if no records are found.
Return a relation that enables strict loading to prevent N+1 queries When strict loading is enabled, accessing associations that weren't preloaded will raise an error
Calculate the sum of values in the specified column. Returns the sum as a number (possibly a floating-point number). Returns 0 if no records match the query or if all values are NULL.
Examples: Order.sum("subtotal") # => 150.75 Order.where(status: "shipped").sum("subtotal") # => 89.50
SQL: SELECT SUM(subtotal) FROM orders SQL: SELECT SUM(subtotal) FROM orders WHERE (orders.status = 'shipped')
Retrieve up to the specified number of records without any implicit ordering.
Retrieve up to the specified number of records without any implicit ordering. Raises RecordNotFound if no records found.
Retrieve a record without any implicit ordering. Raises RecordNotFound if no record found.
Remove all scoping and return a fresh query builder This is useful for bypassing default scopes or removing all existing conditions
Examples: User.where(active: true).unscoped.all # Removes the where condition Book.unscoped.load # Bypasses any default scope
This method removes all scoping and will do a normal query on the table
Support for named placeholder conditions like: User.where("name = :name AND age > :min_age", {name: "John", min_age: 18}) User.where("created_at >= :start_date AND created_at <= :end_date", {start_date: params[:start_date], end_date: params[:end_date]})
Support for NamedTuple syntax: User.where("name = :name", {name: "Alice"})
Named placeholder conditions - must come before variadic method for proper resolution