Многотабличные Модели В Ruby On Rails

Добрый день, дорогой читатель.

Вероятно, вы знакомы с популярным веб-фреймворком Ruby on Rails. Если нет, то эта почта вы сможете найти много интересной и познавательной информации.

Одно из его правил – «Одна модель – один стол».

После этого модель Cat должна брать информацию из таблицы Cats, если не указано другое имя.

Что, если наша модель состоит из нескольких, скажем, шести таблиц? Стандартные методы join/include activerecord здесь больше не помогают.



Постановка задачи
Итак, давайте смоделируем проблему для себя, чтобы проиллюстрировать представленное решение.

Допустим, у нас есть модель продукта.

Графическая структура нашей модели представлена на рисунке:

Многотабличные модели в Ruby on Rails

Основой модели является таблица 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

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.