Rear — полноценный backend интерфейс для ActiveRecord, DataMapper и не только

в 10:30, , рубрики: ruby, web-разработка, админ, админка, Веб-разработка, интерфейсы, метки: , , ,

Очень часто, почти всегда, хочется сократить до максимума время/усилия на создание «админки».

Тем более когда уже все модели в строю и хочется дать клиенту возможность работать с ними,
добавлять записи, редактировать, удалять, редактировать зависимости итд.

Обычно на рутинный процесс создания этого интерфейса уходит непростительно много времени/ресурсов.

Кроме случая когда используются уже готовые наработки.

Именно к таким наработкам относится и Rear.

С его помощью можно создать полноценный админ интерфейс одной строкой — include Rear

Согласен, звучит как SEO-шное заявление, но тем не менее это так.

Полный разбор полёта под катом.

А для нетерпеливых — смотрим демо

Допустим у нас имеется модель Article и нужно за-CRUD-ить записи:

Rear — полноценный backend интерфейс для ActiveRecord, DataMapper и не только

запускаем приложение:

Rear — полноценный backend интерфейс для ActiveRecord, DataMapper и не только

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

Панель обзора

Rear — полноценный backend интерфейс для ActiveRecord, DataMapper и не только

Редактирование

Rear — полноценный backend интерфейс для ActiveRecord, DataMapper и не только

Удобно, но не совсем практично.

Во первых редактировать HTML в textarea как минимум нецелесообразно.
Для исправления ситуации устанавливаем rear-ckeditor и добавляем input :content, :ckeditor, что превратит textarea в удобный Rich Text Editor.
Можно также установить rear-ace и использовать input :content, :ace если нужен Ace вместо CKEditor.

Во вторых надо дать людям возможность фильтрации записей.
Для этого добавляем filter :name.

В третих модели редко бывают одиноки, обычно они идут с различными зависимостями.
В нашем случае Article зависит от Category, так что просто добавляем модель Category а остальное сделает Rear:

Rear — полноценный backend интерфейс для ActiveRecord, DataMapper и не только

и получаем:

дополнительный фильтр:

Rear — полноценный backend интерфейс для ActiveRecord, DataMapper и не только

Rich Text Editor:

Rear — полноценный backend интерфейс для ActiveRecord, DataMapper и не только

редактирование зависимостей:

Rear — полноценный backend интерфейс для ActiveRecord, DataMapper и не только

Установить Rear можно через gem install rear

Попробовать у себя можно скопировав и запустив код ниже.
Наверное не стоит отмечать что нужно также установить data_mapper и dm-mysql-adapter
и до первого запуска выполнить DataMapper.auto_migrate! для создания таблиц, после создания самой базы разумеется.

Код приложения

require 'rear'
require 'rear-ckeditor'
require 'data_mapper'
require 'dm-mysql-adapter'

class Article
  include DataMapper::Resource
  include Rear # вежливо просим Rear построить интерфейс
  input  :content, :ckeditor
  filter :name

  property :id,      Serial
  property :name,    String
  property :content, Text
  has n, :categories, through: Resource
end

class Category
  include DataMapper::Resource

  property :id,   Serial
  property :name, String
  has n, :articles, through: Resource
end

DataMapper.finalize
DataMapper.setup :default, 'mysql://dev@localhost/dev__rear_habrahabr'

Rear.run server: :Thin, port: 2424

А отсюда по подробнее.

Что это такое и с чем его едят?

Это тот-же ActiveAdmin только не для Rails а для Espresso Framework.

Насколько реально использовать Rear в реальном проекте?

Rear ничего от вас не требует, он абсолютно прозрачно интегрируется с новым или существующим проектом.
Он всего-лишь добавляет несколько методов в нужные модели, никак не влияя на остальные части приложения.

Насколько реально настроить интерфейс под свои нужды?

По умолчанию Rear использует тот-же интерфейс для всех приложений.
Если нужен custom интерфейс для определённого приложения, устанавливаем шаблоны к себе в приложение и редактируем.
Теперь все модели будут использовать интерфейс приложения. Если определённая модель требует собственного интерфейса,
создаём папку с именем модели и ставим туда нужные шаблоны.

Приступаем к усвоению

Для начала нужно всего-лишь «инклудить» Rear в нужные модели:

class Foo < ActiveRecord::Base
  include Rear
end

primary_key

Дальше, для правильной работы, Rear-у нужен первичный ключ модели.
Он попытается сам определить pkey и обычно он с этим справляется.
Для исключительных случаев нужно задать pkey в ручную.
Делается это через `primary_key`:

primary_key :ItemID

order_by

По умолчанию Rear выведет записи в том порядке в котором они выдаются ORM.

Когда нужно выводить в определённом порядке, задаём столбцы через `order_by`:

`ActiveRecord`:

  order_by 'name, id DESC'

`DataMapper`:

  order_by :name, :id.desc

items_per_page

По умолчанию Rear выводит по десять записей на каждую страницу.

Изменить это можно через `items_per_page`:

  items_per_page 50

menu_label / menu_position / menu_group

Для лёгкой навигации по администрированым моделям Rear создаст верхнее меню
со списком всех моделей.

По умолчанию будет использоватся имя модели, но это можно изменить через `menu_label`:

class PageModel < ActiveRecord::Base
  include Rear
  menu_label :Pages
  # ...
end

Позиционироваться модели будут в порядке определения.

Если использовать `menu_position`, можно изменить порядок вывода моделей в меню:

class City < ActiveRecord::Base
  include Rear
  menu_position 100
end

class Country < ActiveRecord::Base
  include Rear
  menu_position 1000
end

class State < ActiveRecord::Base
  include Rear
  menu_position 500
end

Это создаст меню вида `Country | State | City` вместо дефолтного `City | Country | State`.

Довольно часто модели сортированы по группам.
Группировать их можно также и в меню Rear-а, если использовать `menu_group`:

class City < ActiveRecord::Base
  include Rear
  menu_group :Location
end

class Country < ActiveRecord::Base
  include Rear
  menu_group :Location
end

class State < ActiveRecord::Base
  include Rear
  menu_group :Location
end

Это создаст всего один пункт меню — Location — при наведении на котором
появятся 3 под-пункта — City, Country и State.

readonly!

Иногда нужно отображать ту или иную модель в режиме только для чтения.

Это легко делается через `readonly!`:

class City < ActiveRecord::Base
  include Rear
  readonly!
end

Теперь города можно будет просматривать без возможности редактирования.

Столбцы

Rear сам найдёт все столбцы и создаст HTML тэги для каждого в соответствии с типом столбца.

Следующие типы столбцов отображаются автоматически:

:string
:text
:date
:time
:datetime
:boolean

Следующие типы надо задавать в ручную:

:ckeditor
:ace
:radio
:checkbox
:select
:password

Для отображения столбца определённого типа используется метод `input`.
Первым аргументом идёт имя столбца а тип идёт вторым:

class Foo < ActiveRecord::Base
  
  include Rear
  input :content, :ckeditor

end

Явное определение столбцов иммет смысл только если нужен custom тип
или нужно передать HTML атрибуты(class, style etc.) или блок для тонкой настройки.

label

По умолчанию, в качестве метки, Rear использует имя столбца.

Более информативную метку можно задать через `label`:

class Foo < ActiveRecord::Base

  input :date, label: 'Select date please'
  # or
  input :date do
    label 'Select date please'
  end
end

Radio/Checkbox/Select

Radio/Checkbox/Select столбцы нуждаются в блоке для корректной работы:

Внутри блока надо задать список опций в виде Array или Hash.

Задаются опции через метод `options`.

Если значения используются также в качестве меток, можно использовать Array:

input :color, :select do
  options 'Red', 'Green', 'Blue'
end

Если же метки отличаются, используем Hash:

input :color, :radio do
  options 'r' => 'Red', 'g' => 'Green', 'b' => 'Blue'
end

Radio и single-Select столбцы отправят данные в виде строки.

А вот Checkbox и multi-Select отправят Array.

Если ORM не совсем корректно преобразовывает Array в строку,
надо установить хук для преобразования перед отправкой.

Делается это через `on_save` метод:

input :color, :checkbox do
  options 'r' => 'Red', 'g' => 'Green', 'b' => 'Blue'
end

on_save do
  params[:color] = params[:color].join(',')
end

Теперь цвета отправляются в виде строки.

Но теперь интерфейс не выделит ни одну опцию, создавая впечатление что цвета не были сохранены.

Это потому что ни ORM ни Rear не знают как правильно преобразовать строку в Array.

Исправляется это с помощью метода `options`, задав блок который преобразует строку в Array:

input :color, :checkbox do
  options 'r' => 'Red', 'g' => 'Green', 'b' => 'Blue' do
    item.color.split(',')
  end
end

on_save do
  params[:color] = params[:color].join(',')
end

Блок имеет доступ к обьекту через `item` и может делать с ним всё что угодно.

В данном случае нам всего-лишь надо преобразовать цвета в Array — `item.color.split(',')`

Блок всегда должен возвращать Array из выбранных значений, даже если сам метод `options` использует Hash.

Rich Text Editor

По умолчанию Rear использует textarea для Text столбцов.

Если нужно превратить textarea в полноценны HTML редактор, устанавливаем rear-ckeditor и ставим тип столбца в ckeditor:

class MyModel < ActiveRecord::Base
  
  include Rear
  input :content, :ckeditor

end

На данный момент Rear использует CKEditor 4й версии.

Если внутри редактора нужно иметь возможность выбирать/загружать картинки,
используем также метод `public_path`, задав путь к папке с картинками:

input :content, :ckeditor do
  public_path '../public/images'
end

readonly / disabled

Иногда нужно отображать определённые столбцы в режиме только для чтения.

Делается это через опцию `readonly`:

input :visits, readonly: true

Важно отметить что readonly эффективен только при редактировании существующих записей.

При создании новых записей readonly столбцы вполне редактируемы.

Если нужно отключить редактирование также при создании новых записей, испрользуем опцию `disabled`:

input :visits, disabled: true

Если же нужно совсем отключить определённый столбец, так чтобы не отображался и не был включён в набор данных, ставим опцию `editor` в false:

input :visits, editor: false

Если нужно исключить столбец также со страниц обзора, ставим опцию `pane` в false:

input :visits, pane: false

row

По умолчанию Rear отображает каждый столбец в собственном ряду — один столбец, один ряд.

Если нужно поставить несколько столбцов в один ряд, используем опцию `row`:

input :red,   row: :Colors
input :green, row: :Colors
input :blue,  row: :Colors

Можно также использовать метод `row` с блоком:

row :Colors do
  input :active
  input :published
  input :archived
end

Если ряд не нуждается в метке, `row` можно вызывать без аргументов.

HTML атрибуты

Когда столбец нуждается в дополнительных атрибутах, передаём их в виде опций:

input :short_text, style: "height: 400px;"

# or

input :short_text do
  html_attrs style: "height: 400px;"
end

Отображение данных

По умолчанию Rear отобразит значение столбца в том виде в котором они пришли из ORM.

Когда значение нужно преобразить, используем метод `value` внутри блока:

input :created_at do
  value { item.created_at.strftime('%d %m, %Y') }
end

Важно отметить что `value` преобразит значение как для страниц редактирования так и для страниц обзора.

Если препроцессинг нужен только для определённой страницы, используем `editor_value` для страницы редактирования и `pane_value` для страницы обзора:

input :created_at do
  pane_value { item.created_at.strftime('%d %m, %Y') }
end

Зависимости

Rear свтоматически найдёт зависимости и создаст интерфейс для управления ими.

Единственное что нужно/можно изменить это исключить определённые зависимости или сделать их readonly.

Исключаем зависимости:

class Page < ActiveRecord::Base
  belongs_to :author

  include Rear
  ignore_assoc :author
  ignore_assoc :tags
  # или
  ignored_assocs :author, :tags
  
end

Отображаем зависимости в режиме только для чтения:

class Page < ActiveRecord::Base
  include Rear
  readonly_assoc :author
  readonly_assoc :tags
  # или
  readonly_assocs :author, :tags
end

На этом пока всё.

Если хаброобщество проявит интерес, будет вторая часть, про фильтры и другие вкусности.

Автор: slivu

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js