Використання ActiveAdmin як бекенду в додатку на Rails 5

Підготовка

Я буду використовувати:

  • Ruby 2.4.0
  • Rails 5 з увімкненим API-ключем
  • SQLite
  • ActiveAdmin

Підготовка додатку:

  1. Створіть папку для додатку:

mkdir rails5_api_activeadmin

cd rails5_api_activeadmin

pic

  1. Створіть Gemset для додатку та встановіть gem rails:
rvm use 2.4.0@rails5_api_activeadmin --ruby-version --create  
gem install rails

pic

  1. Ініціалізуйте новий git-репозиторій та згенеруйте порожній додаток Rails 5:
git init   
rails new . --api

pic

  1. Rails встановлено:

pic

  1. Додаємо папку налаштувань IDE до .gitignore та комітимо зміни:

pic

pic

  1. Тепер запустіть сервер і перевірте, чи працює він (я запускаю на порту 3080, але за замовчуванням — це 3000):
rails s -p 3080

pic

Моделі бази даних

Цей додаток буде використовуватися як сервіс для замовлення їжі з місцевих ресторанів. Тому нам потрібно створити кілька моделей бази даних:

  • Страва (назва, тип, інгредієнти, опис, ціна)
  • Ресторан (назва, опис)
  1. Генерація ресторанної моделі

Я буду використовувати вбудований генератор scaffold у Rails і визначатиму поля, які потрібно створити в базі даних, вказуючи тип поля. За замовчуванням тип — рядок, тому його можна пропустити. Модель Dish буде належати до моделі Restaurant, і Restaurant може мати багато страв. Також я використаю Enumerable для поля типу страви.

rails g scaffold Restaurant title description

rails g scaffold Dish title dish_type:integer ingredients description price:decimal restaurant:belongs_to

pic

Ми можемо проігнорувати попередження в цьому випадку (rails код ще не оновлений під зміни в Ruby 2.4.0).

Я використав трюк Rails, щоб вказати, що модель dish належить до моделі Restaurant.

pic

Тепер мені потрібно вказати, що Restaurant має багато страв, та встановити типи страв:

class Restaurant < ApplicationRecord  
 has_many :dishes  
end
class Dish < ApplicationRecord  
 belongs_to :restaurant  
 enum type: [:european, :pan_asian, :wok, :non_alcohol_drink, :alcohol_drink]  
end

pic

Enum надасть нашому додатку автоматично згенеровані методи для типу страви. І він буде збережений в базі даних як ціле число, починаючи з 0, де кожне наступне число відповідатиме типу страви. Наприклад: 0 для європейської, 1 для паназійської, 2 для вок тощо.

2.

Міграція бази даних, налаштування контролерів і створення тестових даних

Тепер я маю мігрувати базу даних і створити тестові дані:

rails db:migrate  
rails c
Restaurant.create(title: 'First Restaurant', description: "It's first")  
restaurant = Restaurant.first  
restaurant.dishes.burger.create(title: 'Country Burger', ingredients: "beef steak, goat cheese, red pepper, salad,   
 onion, Italian balsamic glaze, olive oil, brioche bread bun, salt, pepper",   
 description: 'Great burger', price: 2.99)

pic

pic

pic

Тепер, якщо я відвідаю http://localhost:3080/restaurants або http://localhost:3080/dishes, я побачу дані, збережені в базі даних, у форматі JSON:

pic

pic

Але я хочу бачити всі страви, які ресторан має на своїй сторінці, а на сторінці страв – назву ресторану. Тому потрібно зробити деякі зміни в відповідних контролерах:

class RestaurantsController < ApplicationController  
 def show  
   render json: @restaurant, include: 'dishes'  
 end  
end

class DishesController < ApplicationController  
 def index  
   @dishes = Dish.all  
   render json: @dishes, include: 'restaurant'  
 end  
end

pic

І тепер я бачу оновлену інформацію у форматі JSON:

pic

Налаштування ActiveAdmin

Перш за все, мені потрібно додати необхідні gems до Gemfile:

gem 'inherited_resources', github: 'activeadmin/inherited_resources'  
gem 'activeadmin', '~> 1.0.0.pre4'  
gem 'ransack', github: 'activerecord-hackery/ransack'  
gem 'kaminari', github: 'amatsuda/kaminari', branch: '0-17-stable'  
gem 'formtastic', github: 'justinfrench/formtastic'  
gem 'draper', github: 'audionerd/draper', branch: 'rails5', ref: 'e816e0e587'  
gem 'activemodel-serializers-xml', github: 'rails/activemodel-serializers-xml'  
gem 'jquery-ui-rails', '~> 5.0.4'

І встановіть їх

bundle install

Після цього потрібно оновити app/controllers/application_controller, змінюючи:

class ApplicationController < ActionController::API  
end

на

class ApplicationController < ActionController::Base  
end

І config/application.rb:

module NewApiApp  
 class Application < Rails::Application  
   # ...  
   config.middleware.use ActionDispatch::Flash  
   config.middleware.use Rack::MethodOverride  
   config.middleware.use ActionDispatch::Cookies  
 end  
end

pic

Тепер я встановлюю ActiveAdmin. Я не буду використовувати жодну аутентифікацію, тому пропускаю цей крок.

rails g active_admin:install --skip-users  
rails db:migrate

Коли я відвідаю http://localhost:3080/admin, я бачу панель інструментів ActiveAdmin:

pic

Створення та налаштування ресурсів ActiveAdmin

Тепер я маю створити ресурси ActiveAdmin:

rails g active_admin:resource Restaurant  
rails g active_admin:resource Dish

Це додасть розділи для створення, перегляду, оновлення та видалення страв і ресторанів, але стандартні вигляди та форми не відповідають моїм потребам, тому я оновлю їх.

По-перше, я оновлюю app/admin/restaurant.rb, щоб на сторінці індексу відображалася кількість страв ресторану та список страв на сторінці перегляду.

Також я вказую ActiveAdmin, які параметри можна змінювати:

ActiveAdmin.register Restaurant do  
 index do  
   column :title  
   column :description  
   column :dishes_count do |product|  
     product.dishes.count  
   end  
   actions  
 end 

 show do |restaurant|  
   attributes_table do  
     row :title  
     row :description  
   end  
   panel 'Dishes' do  
     table_for restaurant.dishes do |t|  
       t.column :title  
       t.column :dish_type  
       t.column :ingredients  
       t.column :description  
       t.column :price  
     end  
   end  
 end  

 permit_params :title, :description  
end

Після цього я оновлю форму редагування страви, щоб я міг вибирати тип страви зі списку. Для цього потрібно створити частину форми в app/views/admin/dishes/_form.html.erb:

<%= semantic_form_for [:admin, @dish], builder: Formtastic::FormBuilder do |f| %>  
 <%= f.semantic_errors %>  
 <%= f.inputs do %>  
   <%= f.input :restaurant_id, as: :select, collection: Hash[Restaurant.all.collect{|r| [r.title, r.id]}], include_blank: false %>  
   <%= f.input :title %>  
   <%= f.input :dish_type, as: :select, collection: Dish.dish_types.keys, include_blank: false %>  
   <%= f.input :description %>  
   <%= f.input :ingredients %>  
   <%= f.input :price %>  
 <% end %>  
 <%= f.actions %>  
<% end %>

І рендерити її з app/admin/dish.rb:

ActiveAdmin.register Dish do  
 form partial: 'form'  
 permit_params :restaurant_id, :title, :dish_type, :description, :ingredients, :price  
end

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

pic

pic

pic

Висновки

ActiveAdmin можна використовувати, якщо потрібно реалізувати бекенд для вашої бази даних. Він гнучкий, настроюваний і легко інтегрується.


Оригінально опубліковано на masterofcode.com/blog

Master of Code пропонує повний спектр послуг з розробки та дизайну інтегрованих веб-, мобільних та чат-бот рішень. Наш великий досвід у різних бізнес-сферах, включаючи освіту, медицину та електронну комерцію, дозволяє нам запропонувати рішення, яке підійде саме для вашого бізнесу. Ми завжди готові допомогти якщо ми можемо зробити щось для вас.

Перекладено з: Using ActiveAdmin as a backend in Rails 5 application