Rails и RABL сортируют дочерний элемент по другой модели, к которой он принадлежит
У меня есть 3 модели:
class City < ActiveRecord::Base
has_many :buildings
end
class Company < ActiveRecord::Base
has_many :buildings
end
class Building < ActiveRecord::Base
belongs_to :city
belongs_to :company
end
Мне нужно показать здание в каждом городе, но отсортировано по их компании так:
city1
company1
building1
building2
company2
building3
city2
company1
building5
building6
building4
company2
building7
building8
Я не могу понять, как сделать запрос или как правильно использовать rabl для создания этой структуры вывода
РЕДАКТИРОВАТЬ:
Вот что я придумал на данный момент:
cities_controlles.rb:
def index
@cities = City.all
@companies = Company.includes(:buildings)
end
index.json.rabl:
collection @cities
attributes :id, :name
node :companies do |city|
@companies.map do |company|
{ id: company.id, name: company.name, buildings:
company.buildings.map do |building|
if building.city_id == city.id
{ id: building.id, name: building.name }
end
end.compact
}
end
end
1 ответ
Есть много способов сделать это в зависимости от того, как следует использовать результат.
Первый способ:
SELECT
cities.name, companies.name, buildings.name
FROM
cities
LEFT JOIN
companies ON companies.city_id = city.id
LEFT JOIN
buildings ON buildings.city_id = city.id
ORDER BY
cities.name, companies.name, buildings.name
Результатом должно быть что-то вроде этого:
city1 | company1 | building1
city1 | company1 | building2
city1 | company2 | building3
city2 | company1 | building4
city2 | company1 | building5
city2 | company1 | building6
city2 | company2 | building7
city2 | company2 | building7
И вы можете делать все, что вы хотите с этим столом.
Второй способ (использование агрегатной функции для получения списка зданий для города и компании):
SELECT
cities.name, companies.name, GROUP_CONCAT(buildings.name)
FROM
cities
LEFT JOIN
companies ON companies.city_id = city.id
LEFT JOIN
buildings ON buildings.city_id = city.id
ORDER BY
cities.name, companies.name
GROUP BY
cities.name, companies.name
Таким образом, Результ должен быть таким:
city1 | company1 | building1, building2
city1 | company2 | building3
city2 | company1 | building4, building5, building6
city2 | company2 | building7, building8
ПРИМЕЧАНИЕ Имя агрегатной функции (GROUP_CONCAT - для MySQL) отличается в СУБД. В Firebird, например, это "LIST"