Let's create for the catalogs
and items
tables models 1: N. Moreover, in the Catalog
model, we will additionally create the total
method, which will refer to the calculated total
column in the resulting query (in fact there is no such column in the catalogs
table).
class Item < ActiveRecord::Base belongs_to :catalog end class Catalog < ActiveRecord::Base has_many :items def total self[:total] end end
Up to Rails 5
Prior to Rails 5, only the joins
method is available, in which the LEFT JOIN
and ON
constructs should be explicitly specified. Moreover, using the assignment of aliases AS
will not work - the table names will have to be written explicitly. In addition, it is necessary to explicitly register all the columns of the catalogs
table, adding them with the expression COUNT(i.id) AS total
.
catalogs = Catalog .joins('LEFT JOIN items ON catalogs.id = items.catalog_id') .select('catalogs.id AS id, catalogs.name AS name, COUNT(items.id) AS total') .group('catalogs.id') catalogs.collect{|x| [x.id, x.name, x.total] } => [[2, "Каталог 2", 2], [1, "Каталог 1", 0], [3, "Каталог 3", 1]]
Rails 5
Beginning with Rails 5, a separate left_joins
method is available in ActiveRecord. Otherwise, the order of forming such requests and getting results remains the same.
catalogs = Catalog .left_joins(:items) .select('catalogs.id AS id, catalogs.name AS name, COUNT(items.id) AS total') .group('catalogs.id') catalogs.collect{|x| [x.id, x.name, x.total] } => [[2, "Каталог 2", 2], [1, "Каталог 1", 0], [3, "Каталог 3", 1]]