Добрый день, дорогой читатель.
Вероятно, вы знакомы с популярным веб-фреймворком Ruby on Rails. Если нет, то эта почта вы сможете найти много интересной и познавательной информации.
Одно из его правил – «Одна модель – один стол».
После этого модель Cat должна брать информацию из таблицы Cats, если не указано другое имя.
Что, если наша модель состоит из нескольких, скажем, шести таблиц? Стандартные методы join/include activerecord здесь больше не помогают.
Постановка задачи
Итак, давайте смоделируем проблему для себя, чтобы проиллюстрировать представленное решение.Допустим, у нас есть модель продукта.
Графическая структура нашей модели представлена на рисунке:
Основой модели является таблица items. Он связан одиночными ссылками с таблицами цветов, типов, магазинов и производителей.
В свою очередь, два последних адреса связаны полиморфными отношениями.
Одним из решений в этом случае может быть создание простого запроса такого типа:
В ответ мы получим коллекцию хешей, ключи которых содержат имена столбцов или псевдонимы.ActiveRecord::Base.connection.execute('SELECT items.*, colors.name as color, types.name as type, stores.name as store_name .
FROM items LEFT JOIN colors ON items.color_id = colors.id LEFT JOIN types ON items.type_id = types.id LEFT JOIN stores ON items.store_id = stores.id .
Но этот подход имеет много недостатков.
Во-первых, нет нормального поиска по значениям.
Во-вторых, если записей большое количество, вам придется создать свою пагинацию.
Но многие люди любят Rails за ActiveRecord, библиотеки will_paginate, kaminari, Meta_search. Поэтому нам нужно связать наш большой запрос с ActiveRecord.
Давайте вспомним о Sql View
Для этого нам необходимо познакомиться, если вы еще не знакомы, с представлениями в sql. Представление (VIEW) — это объект базы данных, который является результатом запроса к базе данных, определенного с помощью инструкции SELECT при доступе к представлению.Но представления также могут быть ошибочно приняты за виртуальную таблицу, доступную только для чтения.
Более подробно на примере mysql говорят о представлении Здесь .
Для нас важно, чтобы activerecord рассматривал ее как таблицу и предоставлял ее мощный потенциал.
Сначала давайте создадим миграцию: rails g migration AddProducts
В нем мы напишем следующее: def up
execute '
CREATE VIEW products AS
SELECT i.id AS id, i.name AS name, i.weight AS weight, i.size AS size, c.name as color,
t.name as type, s.name AS store_name, sa.street AS store_street, sa.city AS store_city,
sa.country AS store_country, sa.phone AS store_phone, m.name AS manufacture_name,
ma.street AS manufacture_street, ma.city AS manufacture_city,
ma.country AS manufacture_country, ma.phone AS manufacture_phone
FROM items AS i
LEFT JOIN colors AS c ON i.color_id = c.id
LEFT JOIN types AS t ON i.type_id = t.id
LEFT JOIN stores AS s ON i.store_id = s.id
LEFT JOIN addresses AS sa ON s.id = sa.addressat_id AND sa.addressat_type = "Store"
LEFT JOIN manufactures AS m ON i.manufacture_id = m.id
LEFT JOIN addresses AS ma ON m.id = ma.addressat_id AND ma.addressat_type = "Manufacture"
'
end
def down
execute 'DROP VIEW products '
end
Далее давайте создадим модель продукта, сделав ее доступной только для чтения: class Products < ActiveRecord::Base
# Prevent creation of new records and modification to existing records
def readonly?
return true
end
# Prevent objects from being destroyed
def before_destroy
raise ActiveRecord::ReadOnlyRecord
end
end
Теперь мы можем использовать всю мощь activerecord, arel и других библиотек для извлечения, фильтрации и разбиения на страницы нашей сложной модели.
blue_guitars_in_kiev = Product.where(:color => 'Blue', :type => 'Guitar', :store_city => 'Kiev')
blue_guitars_in_kiev.each do |product|
puts product.store_name
end
Запросы выполняются быстро, за одну транзакцию, а Ruby-код сведен к минимуму.
Единственным недостатком этого решения является необходимость постоянно заново создавать эту виртуальную таблицу при изменении имени или удалении столбца.
Вот и все.
Надеюсь мой пост был вам полезен, всего доброго.
Теги: #ruby onrails #activerecord #sql view #ruby onrails
-
Почтовые Услуги
19 Oct, 24 -
Интервью О Прошлом И Будущем Библиотек C++
19 Oct, 24 -
Эта Черно-Черная Пятница
19 Oct, 24 -
Ленивые Потоки: Необязательный Параллелизм
19 Oct, 24 -
Убогие И Грязные Комментарии, Темы И Т.д.
19 Oct, 24