SlideShare a Scribd company logo
1 of 38
Download to read offline
Корпоративное приложение на Rails. 
Отчет после года разработки 
Андрей Колешко 
@ka8725
Что представляет из себя 
наше приложение 
• Полно бизнес логики 
• Работа с деньгами клиентов 
• Общение со сторонними системами 
• Очереди обработки данных (sidekiq) 
• Асинхронность 
• Поддержка плагинов через Rails engines 
• Звездолет
Приблизительное состояние кода в 
проекте
Быть или не быть? 
• Посмотрим с какими проблемами мы 
столкнулись и как с ними боролись 
• Какие проблемы не решены 
• Попробуем сделать выводы, можно ли 
использовать Rails в коммерческих приложениях
Модульность 
• Ruby modules 
• Rails engines
Ruby modules 
• Многие гемы просто не готовы к тому, что мы будем 
использовать Ruby модули 
• DataGrid - не было возможности изменить шаблоны для 
client и admin области 
• Draper - для работы декоратора в пространстве имен 
приходится писать магические строчки 
• InheritedResources - поиск ресурса (AR модельки) в 
модуле не был реализован 
• Rails - polymorphic routes генерировали неправильные 
helper-методы
Rails Engines 
• Нельзя использовать разные версии gems в ядре и плагине 
• В Ruby нет интерфейсов. Нельзя заставить плагины 
реализовать все методы, которые нам нужны 
• Тестирование Rails Engines в контексте ядра - 
болезненный процесс 
• rake railties:install:migrations постоянно генерирует 
новые файлы 
• Установленный Rails Engine может поломать все 
приложение. У него есть доступ ко всему
Имеем дело со всеми известными 
проблемами модульного приложения
Как мы преодолеваем 
проблемы сейчас 
• Pull request’ы в гемы, которые не готовы к 
использованию Ruby модулей 
• Для плагинов предоставляем миксины 
• Общение с плагинами стараемся выстраивать через 
самописный Pub-Sub, основанный на 
ActiveSupport::Notifications- 
• Тестируются плагины вручную- 
• Собственный регистратор плагинов
Пример Pub-Sub 
# Core 
Publisher.broadcast_event('user.created', {user_id: 1}) 
! 
# Plugin 
Subscriber.subscribe('user.created') do |event| 
payload = event.payload 
puts payload[:user_id] 
end 
http://goo.gl/QJxujy
Особенности нашего Pub- 
Sub 
• Однопоточный 
• Нет обратной связи. Сообщения 
однонаправленные
Собственный регистратор 
плагинов 
• Дает простую установку копированием плагина 
в нужную папку 
• Контролируемый процесс подключения плагина 
к системе 
• Плагин - Rails engine
Преимущества Rails 
engines как модулей 
• В плагинах можно изменить все. View, Routes, 
Controllers, Models, Helpers… 
• Быстро работает (нет сторонних вызовов)
ActiveRecord 
• Избегаем nested_attributes 
• Используем FormObjects, ServiceObjects, 
QueryObjects, PolicyObjects 
• В моделе остается только отображение данных и 
самые необходимые валидации, ассоциации 
• Избегаем Observers и Callbacks
Исключение для 
использования callbacks 
• Отправка сообщения в очередь для фоновой 
обработки 
• Не изменяет состояние объектов
Observers 
• Правила использования не отличаются от 
callbacks 
• Ведут к более запутанному коду чем callbacks 
• Лучше никогда не использовать
Завязались окончательно?
Возможноcть развязать 
узлы в тестах 
! 
• Отключаем все колбэки в моделях 
• Включаем колбэки в тестах в тех местах, где их 
вызов необходим 
• Не используйте этот подход в новых 
приложениях!
Возможность оставить 
тесты рабочими 
class ActiveRecord::Base 
cattr_accessor :skip_callbacks- 
end 
! 
class User < ActiveRecord::Base 
after_create :send_invitation, unless: :skip_callbacks 
def send_invitation 
puts 'hello' 
end 
end 
! 
ActiveRecord::Base.skip_callbacks = true 
User.create # => 
ActiveRecord::Base.skip_callbacks = false 
User.create # => 'hello'
Слой View 
• Проблема с длинными именами helper-методов 
• Использование instance переменных (@var) во 
view 
• Рендеринг таблиц 
• fields_for и nested_attributes 
• Фарш AngularJS
Длинные имена helper- 
методов 
plugin_exchange_client_account_application_contact_ 
contact_distribution_group_path(parent.account, 
parent.core_application, parent, resource) 
! 
Всего 141 символ!
Решение 
# Controllers 
class SomeController < ApplicationController 
helper_method :submit_path 
helper_method :cancel_path 
! 
private 
! 
def submit_path 
any_size_of_helper_method_you_want_submit_path( 
arg1, 
arg2, 
… 
) 
end 
! 
def cancel_path 
any_size_of_helper_method_you_want_cancel_path( 
arg1, 
arg2, 
… 
) 
end 
! 
end
Решение 
# Views 
! 
= form_tag submit_path do 
= link_to 'Cancel', cancel_path
Преимущества решения 
• “Чистый”, читабельный и более надежный код во 
view 
• HAML вам сважет спасибо 
! 
PS. Не используйте HAML! Есть более удачный 
шаблонизатор - SLIM.
Helper-методы вместо @var 
• Ошибка рендеринга более адекватная (undefined 
method my_helper_method вместо 
undefined_method “…” for nil class)
Рендеринг таблиц 
• DataGrid- 
• Сортировка и фильтрация из коробки 
• Беспроблемная интеграция с пагинаторами и 
полнотектовыми движками (через свои scopes) 
• Возможность изменять шаблоны таблицы 
• view занимают всего 3 (!!!) строчки кода 
• и другое - https://github.com/bogdan/datagrid
fields_for и 
nested_attributes 
• В FormObjects сложно обрабатывать магические 
хеши nested_attributes 
• В большинстве случаев необходимо 
использовать свой primary key для поиска 
записи на обновление в базе. А не id, который 
зашит в rails хардкором 
• Огромные имена переменных ассоциаций
fields_for и 
nested_attributes 
- form_object.locations.each do |location| 
= f.fields_for 'locations[]', location, include_id: false, 
index: nil do |ff| 
# include_id: false - предотвращает генерацию 
hidden field c id, т.к. нас это не устраивает 
# index: nil - не включать index в название 
сгенерированного аттрибута
Преимущества данного 
подхода 
• Имена параметров чистые и понятные 
• Возможность передавать на сервер свой primary 
ключ для поиска модели на обновление 
• Проще обработка в FormObjects
Фарш AngularJS 
• Т.к. состояние объектов хранится на сервере 
необходимо вручную вызывать ng-init 
• В каждый input необходимо передать ng-model 
атрибут 
• Если в ng-init забыт атрибут, который связан с ng-model, 
то получим некорректное отображение 
объекта на форме 
• Что делать при успешном сохранении формы? 
Reload страницы? - Теряем flash сообщения
Разработка на Rails 
быстрая? 
• Только для небольших 
приложений 
• Огромное количество кода 
препятствует быстрой 
разработке
Rails way Enterprise way
Выводы 
• Rails отлично подходит для создания прототипов- 
• К модульности и огромным приложениям Rails не готов 
• В сложных приложениях приходится отказываться от 
многих магических палочек Rails- 
• Это ведет к увелечению собственного кода 
• Код требует ухода. Знание шаблонов 
проектирования, принципов проектирования 
классов (SOLID) здесь просто необходимо
Что в Ruby хорошо? 
• Писать DSL 
• Сам язык очень 
выразительный 
• Код приятно писать и читать 
• И на этом все :(
Решились писать Enterprise 
на Rails? 
• Нужен ли Вам Rails? Может, достаточно взять Sinatra + Grape, 
если у вас будет SPA (Single Page Application)? 
• Тщательно обрабатывайте требования. Выясняйте Use Cases- 
• На основании UseCases стройте доменную модель (набор 
классов и их взаимодействия). 
• Не привязывайтесь к ActiveRecord. ActiveRecord - только для 
представления данных! 
• Тщательно выбирайте гемы. Подумайте 100500 раз прежде чем 
выбрать InheritedResources, например. 
• Следуйте принципам SOLID, не нарушайте закон Деметры
Литература 
1. http://goo.gl/GyqjXg - 7 steps to get started with Clean 
Architecture in Ruby 
2. http://goo.gl/g0VA1 - 7 Patterns to Refactor Fat ActiveRecord 
Models 
3. http://goo.gl/lz1fEX - Ruby Midwest 2011 - Keynote: Architecture 
the Lost Years by Robert Martin 
4. http://goo.gl/MP6L7Z - High-Low Testing 
5. http://goo.gl/aI3kdc - Growing Rails Applications in Practice 
6. http://goo.gl/9KsmM - Принципы проектирования классов 
(S.O.L.I.D.)
На правах рекламы 
! 
Основы Rake 
Простые примеры применения 
в реальном мире 
Сравнение с конкурентом - 
Thor
Вопросы? 
Андрей Колешко 
@ka8725- 
ka8725@gmail.com

More Related Content

Viewers also liked

Ruby on Rails at HackDay in Saint Petersburg
Ruby on Rails at HackDay in Saint PetersburgRuby on Rails at HackDay in Saint Petersburg
Ruby on Rails at HackDay in Saint PetersburgAlexander Krass
 
Ruby: интерпретируемый, динамичный, человеколюбивый
Ruby: интерпретируемый, динамичный, человеколюбивыйRuby: интерпретируемый, динамичный, человеколюбивый
Ruby: интерпретируемый, динамичный, человеколюбивыйAlex Mikitenko
 
Антон Веснин - "Обзорное сравнение серверов приложений ruby-on-rails"
Антон Веснин - "Обзорное сравнение серверов приложений ruby-on-rails"Антон Веснин - "Обзорное сравнение серверов приложений ruby-on-rails"
Антон Веснин - "Обзорное сравнение серверов приложений ruby-on-rails"railsclub
 
13 HappyDev-lite-2015 autumn. Руслан Шарипов. Ruby, making programmers happy.
13 HappyDev-lite-2015 autumn. Руслан Шарипов. Ruby, making programmers happy.13 HappyDev-lite-2015 autumn. Руслан Шарипов. Ruby, making programmers happy.
13 HappyDev-lite-2015 autumn. Руслан Шарипов. Ruby, making programmers happy.HappyDev-lite
 
1000 запросов в секунду на rails (Макс Лапшин)
1000 запросов в секунду на rails (Макс Лапшин)1000 запросов в секунду на rails (Макс Лапшин)
1000 запросов в секунду на rails (Макс Лапшин)Ontico
 
Как сделать контрибут в Ruby on Rails
Как сделать контрибут в Ruby on RailsКак сделать контрибут в Ruby on Rails
Как сделать контрибут в Ruby on RailsYaroslav Markin
 
10 reasons I love RubyOnRails
10 reasons I love RubyOnRails10 reasons I love RubyOnRails
10 reasons I love RubyOnRailsPavel Gabriel
 
Deploy.rb, Ilya Zykin, Rails club2016
Deploy.rb, Ilya Zykin, Rails club2016Deploy.rb, Ilya Zykin, Rails club2016
Deploy.rb, Ilya Zykin, Rails club2016zykin-ilya
 
Александр Тищенко - "Антикризисная презентация"
Александр Тищенко - "Антикризисная презентация"Александр Тищенко - "Антикризисная презентация"
Александр Тищенко - "Антикризисная презентация"railsclub
 
Призма24 - Маркетплейсы.
Призма24 - Маркетплейсы.Призма24 - Маркетплейсы.
Призма24 - Маркетплейсы.Vitalii Tytskyi
 
I18n ruby-приложений
I18n ruby-приложенийI18n ruby-приложений
I18n ruby-приложенийAndrey Sitnik
 
Фронтенд для рубиста
Фронтенд для рубистаФронтенд для рубиста
Фронтенд для рубистаKir Shatrov
 

Viewers also liked (20)

Ruby on Rails at HackDay in Saint Petersburg
Ruby on Rails at HackDay in Saint PetersburgRuby on Rails at HackDay in Saint Petersburg
Ruby on Rails at HackDay in Saint Petersburg
 
Ruby: интерпретируемый, динамичный, человеколюбивый
Ruby: интерпретируемый, динамичный, человеколюбивыйRuby: интерпретируемый, динамичный, человеколюбивый
Ruby: интерпретируемый, динамичный, человеколюбивый
 
Антон Веснин - "Обзорное сравнение серверов приложений ruby-on-rails"
Антон Веснин - "Обзорное сравнение серверов приложений ruby-on-rails"Антон Веснин - "Обзорное сравнение серверов приложений ruby-on-rails"
Антон Веснин - "Обзорное сравнение серверов приложений ruby-on-rails"
 
13 HappyDev-lite-2015 autumn. Руслан Шарипов. Ruby, making programmers happy.
13 HappyDev-lite-2015 autumn. Руслан Шарипов. Ruby, making programmers happy.13 HappyDev-lite-2015 autumn. Руслан Шарипов. Ruby, making programmers happy.
13 HappyDev-lite-2015 autumn. Руслан Шарипов. Ruby, making programmers happy.
 
1000 запросов в секунду на rails (Макс Лапшин)
1000 запросов в секунду на rails (Макс Лапшин)1000 запросов в секунду на rails (Макс Лапшин)
1000 запросов в секунду на rails (Макс Лапшин)
 
Oleg Gorbunov Action cable
Oleg Gorbunov Action cableOleg Gorbunov Action cable
Oleg Gorbunov Action cable
 
Ruby on Rails for noobs
Ruby on Rails for noobsRuby on Rails for noobs
Ruby on Rails for noobs
 
R18n
R18nR18n
R18n
 
Assets Pipeline
Assets PipelineAssets Pipeline
Assets Pipeline
 
RSpec. Part 2
RSpec. Part 2RSpec. Part 2
RSpec. Part 2
 
RSpec. Part 3
RSpec. Part 3RSpec. Part 3
RSpec. Part 3
 
Как сделать контрибут в Ruby on Rails
Как сделать контрибут в Ruby on RailsКак сделать контрибут в Ruby on Rails
Как сделать контрибут в Ruby on Rails
 
10 reasons I love RubyOnRails
10 reasons I love RubyOnRails10 reasons I love RubyOnRails
10 reasons I love RubyOnRails
 
Deploy.rb, Ilya Zykin, Rails club2016
Deploy.rb, Ilya Zykin, Rails club2016Deploy.rb, Ilya Zykin, Rails club2016
Deploy.rb, Ilya Zykin, Rails club2016
 
Александр Тищенко - "Антикризисная презентация"
Александр Тищенко - "Антикризисная презентация"Александр Тищенко - "Антикризисная презентация"
Александр Тищенко - "Антикризисная презентация"
 
Rails Concerns
Rails ConcernsRails Concerns
Rails Concerns
 
Призма24 - Маркетплейсы.
Призма24 - Маркетплейсы.Призма24 - Маркетплейсы.
Призма24 - Маркетплейсы.
 
RSpec. Part 1
RSpec. Part 1RSpec. Part 1
RSpec. Part 1
 
I18n ruby-приложений
I18n ruby-приложенийI18n ruby-приложений
I18n ruby-приложений
 
Фронтенд для рубиста
Фронтенд для рубистаФронтенд для рубиста
Фронтенд для рубиста
 

Similar to Корпоративное приложение на Rails

09 - Web-технологии. MVC фреймворки
09 - Web-технологии. MVC фреймворки09 - Web-технологии. MVC фреймворки
09 - Web-технологии. MVC фреймворкиRoman Brovko
 
Владимир Никонов "Вызовы при разработке enterprise продукта"
Владимир Никонов "Вызовы при разработке enterprise продукта"Владимир Никонов "Вызовы при разработке enterprise продукта"
Владимир Никонов "Вызовы при разработке enterprise продукта"Fwdays
 
JSLab. Дмитрий Смолин, Дмитрий Филипенко. "React и Webpack с помощью кирки, л...
JSLab. Дмитрий Смолин, Дмитрий Филипенко. "React и Webpack с помощью кирки, л...JSLab. Дмитрий Смолин, Дмитрий Филипенко. "React и Webpack с помощью кирки, л...
JSLab. Дмитрий Смолин, Дмитрий Филипенко. "React и Webpack с помощью кирки, л...GeeksLab Odessa
 
Разговор про Java 9. Extended version
Разговор про Java 9. Extended versionРазговор про Java 9. Extended version
Разговор про Java 9. Extended versionIvan Krylov
 
Gradle. Новый уровень автоматизации для Android
Gradle. Новый уровень автоматизации для AndroidGradle. Новый уровень автоматизации для Android
Gradle. Новый уровень автоматизации для AndroidAnton Rutkevich
 
Javascript-фреймворки: должен остаться только один / Аверин Сергей (Acronis)
Javascript-фреймворки: должен остаться только один / Аверин Сергей (Acronis)Javascript-фреймворки: должен остаться только один / Аверин Сергей (Acronis)
Javascript-фреймворки: должен остаться только один / Аверин Сергей (Acronis)Ontico
 
Javascript-фреймворки:
 должен остаться только один
Javascript-фреймворки:
 должен остаться только одинJavascript-фреймворки:
 должен остаться только один
Javascript-фреймворки:
 должен остаться только одинSergey Xek
 
Gradle. Новый уровень автоматизации для Android
Gradle. Новый уровень автоматизации для AndroidGradle. Новый уровень автоматизации для Android
Gradle. Новый уровень автоматизации для AndroidSQALab
 
2015-12-05 Сергей Аверин - Javascript-фреймворки: должен остаться только один
2015-12-05 Сергей Аверин - Javascript-фреймворки: должен остаться только один2015-12-05 Сергей Аверин - Javascript-фреймворки: должен остаться только один
2015-12-05 Сергей Аверин - Javascript-фреймворки: должен остаться только одинHappyDev
 
Refactorings with RubyMine
Refactorings with RubyMineRefactorings with RubyMine
Refactorings with RubyMineavokin
 
Оптимизация производительности нагруженных веб-систем на Java
Оптимизация производительности нагруженных веб-систем на JavaОптимизация производительности нагруженных веб-систем на Java
Оптимизация производительности нагруженных веб-систем на JavaAlex Chistyakov
 
Юрий Василевский "Автоматизация в XCode"
Юрий Василевский "Автоматизация в XCode"Юрий Василевский "Автоматизация в XCode"
Юрий Василевский "Автоматизация в XCode"Yandex
 
Юрий Василевский «Автоматизация в XCode»
Юрий Василевский «Автоматизация в XCode»Юрий Василевский «Автоматизация в XCode»
Юрий Василевский «Автоматизация в XCode»Yandex
 
Разработка мобильного и веб интерфейса для Caché
Разработка мобильного и веб интерфейса для CachéРазработка мобильного и веб интерфейса для Caché
Разработка мобильного и веб интерфейса для CachéInterSystems CEE
 
ASP.NET, MVC, ASP.NET MVC
ASP.NET, MVC, ASP.NET MVCASP.NET, MVC, ASP.NET MVC
ASP.NET, MVC, ASP.NET MVCGetDev.NET
 
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...Stas Vyschepan
 
Ember.js - Назад в Будущее - Odessa JS 2014
Ember.js - Назад в Будущее - Odessa JS 2014Ember.js - Назад в Будущее - Odessa JS 2014
Ember.js - Назад в Будущее - Odessa JS 2014Andrey Listochkin
 

Similar to Корпоративное приложение на Rails (20)

Sivko
SivkoSivko
Sivko
 
09 - Web-технологии. MVC фреймворки
09 - Web-технологии. MVC фреймворки09 - Web-технологии. MVC фреймворки
09 - Web-технологии. MVC фреймворки
 
Владимир Никонов "Вызовы при разработке enterprise продукта"
Владимир Никонов "Вызовы при разработке enterprise продукта"Владимир Никонов "Вызовы при разработке enterprise продукта"
Владимир Никонов "Вызовы при разработке enterprise продукта"
 
Little Service in 2h
Little Service in 2hLittle Service in 2h
Little Service in 2h
 
JSLab. Дмитрий Смолин, Дмитрий Филипенко. "React и Webpack с помощью кирки, л...
JSLab. Дмитрий Смолин, Дмитрий Филипенко. "React и Webpack с помощью кирки, л...JSLab. Дмитрий Смолин, Дмитрий Филипенко. "React и Webpack с помощью кирки, л...
JSLab. Дмитрий Смолин, Дмитрий Филипенко. "React и Webpack с помощью кирки, л...
 
Разговор про Java 9. Extended version
Разговор про Java 9. Extended versionРазговор про Java 9. Extended version
Разговор про Java 9. Extended version
 
Gradle. Новый уровень автоматизации для Android
Gradle. Новый уровень автоматизации для AndroidGradle. Новый уровень автоматизации для Android
Gradle. Новый уровень автоматизации для Android
 
Javascript-фреймворки: должен остаться только один / Аверин Сергей (Acronis)
Javascript-фреймворки: должен остаться только один / Аверин Сергей (Acronis)Javascript-фреймворки: должен остаться только один / Аверин Сергей (Acronis)
Javascript-фреймворки: должен остаться только один / Аверин Сергей (Acronis)
 
Javascript-фреймворки:
 должен остаться только один
Javascript-фреймворки:
 должен остаться только одинJavascript-фреймворки:
 должен остаться только один
Javascript-фреймворки:
 должен остаться только один
 
Gradle. Новый уровень автоматизации для Android
Gradle. Новый уровень автоматизации для AndroidGradle. Новый уровень автоматизации для Android
Gradle. Новый уровень автоматизации для Android
 
2015-12-05 Сергей Аверин - Javascript-фреймворки: должен остаться только один
2015-12-05 Сергей Аверин - Javascript-фреймворки: должен остаться только один2015-12-05 Сергей Аверин - Javascript-фреймворки: должен остаться только один
2015-12-05 Сергей Аверин - Javascript-фреймворки: должен остаться только один
 
Refactorings with RubyMine
Refactorings with RubyMineRefactorings with RubyMine
Refactorings with RubyMine
 
Оптимизация производительности нагруженных веб-систем на Java
Оптимизация производительности нагруженных веб-систем на JavaОптимизация производительности нагруженных веб-систем на Java
Оптимизация производительности нагруженных веб-систем на Java
 
Юрий Василевский "Автоматизация в XCode"
Юрий Василевский "Автоматизация в XCode"Юрий Василевский "Автоматизация в XCode"
Юрий Василевский "Автоматизация в XCode"
 
Юрий Василевский «Автоматизация в XCode»
Юрий Василевский «Автоматизация в XCode»Юрий Василевский «Автоматизация в XCode»
Юрий Василевский «Автоматизация в XCode»
 
Разработка мобильного и веб интерфейса для Caché
Разработка мобильного и веб интерфейса для CachéРазработка мобильного и веб интерфейса для Caché
Разработка мобильного и веб интерфейса для Caché
 
ASP.NET, MVC, ASP.NET MVC
ASP.NET, MVC, ASP.NET MVCASP.NET, MVC, ASP.NET MVC
ASP.NET, MVC, ASP.NET MVC
 
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
 
Migrate!
Migrate!Migrate!
Migrate!
 
Ember.js - Назад в Будущее - Odessa JS 2014
Ember.js - Назад в Будущее - Odessa JS 2014Ember.js - Назад в Будущее - Odessa JS 2014
Ember.js - Назад в Будущее - Odessa JS 2014
 

More from Andrei Kaleshka

More from Andrei Kaleshka (7)

How we prevented account sharing with MFA
How we prevented account sharing with MFAHow we prevented account sharing with MFA
How we prevented account sharing with MFA
 
Business domain isolation in db
Business domain isolation in dbBusiness domain isolation in db
Business domain isolation in db
 
Rails data migrations
Rails data migrationsRails data migrations
Rails data migrations
 
Ruby exceptions
Ruby exceptionsRuby exceptions
Ruby exceptions
 
Rails3 way
Rails3 wayRails3 way
Rails3 way
 
Complete ruby code
Complete ruby codeComplete ruby code
Complete ruby code
 
Rails 3 assets pipeline
Rails 3 assets pipelineRails 3 assets pipeline
Rails 3 assets pipeline
 

Корпоративное приложение на Rails

  • 1. Корпоративное приложение на Rails. Отчет после года разработки Андрей Колешко @ka8725
  • 2. Что представляет из себя наше приложение • Полно бизнес логики • Работа с деньгами клиентов • Общение со сторонними системами • Очереди обработки данных (sidekiq) • Асинхронность • Поддержка плагинов через Rails engines • Звездолет
  • 4. Быть или не быть? • Посмотрим с какими проблемами мы столкнулись и как с ними боролись • Какие проблемы не решены • Попробуем сделать выводы, можно ли использовать Rails в коммерческих приложениях
  • 5. Модульность • Ruby modules • Rails engines
  • 6. Ruby modules • Многие гемы просто не готовы к тому, что мы будем использовать Ruby модули • DataGrid - не было возможности изменить шаблоны для client и admin области • Draper - для работы декоратора в пространстве имен приходится писать магические строчки • InheritedResources - поиск ресурса (AR модельки) в модуле не был реализован • Rails - polymorphic routes генерировали неправильные helper-методы
  • 7. Rails Engines • Нельзя использовать разные версии gems в ядре и плагине • В Ruby нет интерфейсов. Нельзя заставить плагины реализовать все методы, которые нам нужны • Тестирование Rails Engines в контексте ядра - болезненный процесс • rake railties:install:migrations постоянно генерирует новые файлы • Установленный Rails Engine может поломать все приложение. У него есть доступ ко всему
  • 8. Имеем дело со всеми известными проблемами модульного приложения
  • 9. Как мы преодолеваем проблемы сейчас • Pull request’ы в гемы, которые не готовы к использованию Ruby модулей • Для плагинов предоставляем миксины • Общение с плагинами стараемся выстраивать через самописный Pub-Sub, основанный на ActiveSupport::Notifications- • Тестируются плагины вручную- • Собственный регистратор плагинов
  • 10. Пример Pub-Sub # Core Publisher.broadcast_event('user.created', {user_id: 1}) ! # Plugin Subscriber.subscribe('user.created') do |event| payload = event.payload puts payload[:user_id] end http://goo.gl/QJxujy
  • 11. Особенности нашего Pub- Sub • Однопоточный • Нет обратной связи. Сообщения однонаправленные
  • 12. Собственный регистратор плагинов • Дает простую установку копированием плагина в нужную папку • Контролируемый процесс подключения плагина к системе • Плагин - Rails engine
  • 13. Преимущества Rails engines как модулей • В плагинах можно изменить все. View, Routes, Controllers, Models, Helpers… • Быстро работает (нет сторонних вызовов)
  • 14. ActiveRecord • Избегаем nested_attributes • Используем FormObjects, ServiceObjects, QueryObjects, PolicyObjects • В моделе остается только отображение данных и самые необходимые валидации, ассоциации • Избегаем Observers и Callbacks
  • 15. Исключение для использования callbacks • Отправка сообщения в очередь для фоновой обработки • Не изменяет состояние объектов
  • 16. Observers • Правила использования не отличаются от callbacks • Ведут к более запутанному коду чем callbacks • Лучше никогда не использовать
  • 18. Возможноcть развязать узлы в тестах ! • Отключаем все колбэки в моделях • Включаем колбэки в тестах в тех местах, где их вызов необходим • Не используйте этот подход в новых приложениях!
  • 19. Возможность оставить тесты рабочими class ActiveRecord::Base cattr_accessor :skip_callbacks- end ! class User < ActiveRecord::Base after_create :send_invitation, unless: :skip_callbacks def send_invitation puts 'hello' end end ! ActiveRecord::Base.skip_callbacks = true User.create # => ActiveRecord::Base.skip_callbacks = false User.create # => 'hello'
  • 20. Слой View • Проблема с длинными именами helper-методов • Использование instance переменных (@var) во view • Рендеринг таблиц • fields_for и nested_attributes • Фарш AngularJS
  • 21. Длинные имена helper- методов plugin_exchange_client_account_application_contact_ contact_distribution_group_path(parent.account, parent.core_application, parent, resource) ! Всего 141 символ!
  • 22. Решение # Controllers class SomeController < ApplicationController helper_method :submit_path helper_method :cancel_path ! private ! def submit_path any_size_of_helper_method_you_want_submit_path( arg1, arg2, … ) end ! def cancel_path any_size_of_helper_method_you_want_cancel_path( arg1, arg2, … ) end ! end
  • 23. Решение # Views ! = form_tag submit_path do = link_to 'Cancel', cancel_path
  • 24. Преимущества решения • “Чистый”, читабельный и более надежный код во view • HAML вам сважет спасибо ! PS. Не используйте HAML! Есть более удачный шаблонизатор - SLIM.
  • 25. Helper-методы вместо @var • Ошибка рендеринга более адекватная (undefined method my_helper_method вместо undefined_method “…” for nil class)
  • 26. Рендеринг таблиц • DataGrid- • Сортировка и фильтрация из коробки • Беспроблемная интеграция с пагинаторами и полнотектовыми движками (через свои scopes) • Возможность изменять шаблоны таблицы • view занимают всего 3 (!!!) строчки кода • и другое - https://github.com/bogdan/datagrid
  • 27. fields_for и nested_attributes • В FormObjects сложно обрабатывать магические хеши nested_attributes • В большинстве случаев необходимо использовать свой primary key для поиска записи на обновление в базе. А не id, который зашит в rails хардкором • Огромные имена переменных ассоциаций
  • 28. fields_for и nested_attributes - form_object.locations.each do |location| = f.fields_for 'locations[]', location, include_id: false, index: nil do |ff| # include_id: false - предотвращает генерацию hidden field c id, т.к. нас это не устраивает # index: nil - не включать index в название сгенерированного аттрибута
  • 29. Преимущества данного подхода • Имена параметров чистые и понятные • Возможность передавать на сервер свой primary ключ для поиска модели на обновление • Проще обработка в FormObjects
  • 30. Фарш AngularJS • Т.к. состояние объектов хранится на сервере необходимо вручную вызывать ng-init • В каждый input необходимо передать ng-model атрибут • Если в ng-init забыт атрибут, который связан с ng-model, то получим некорректное отображение объекта на форме • Что делать при успешном сохранении формы? Reload страницы? - Теряем flash сообщения
  • 31. Разработка на Rails быстрая? • Только для небольших приложений • Огромное количество кода препятствует быстрой разработке
  • 33. Выводы • Rails отлично подходит для создания прототипов- • К модульности и огромным приложениям Rails не готов • В сложных приложениях приходится отказываться от многих магических палочек Rails- • Это ведет к увелечению собственного кода • Код требует ухода. Знание шаблонов проектирования, принципов проектирования классов (SOLID) здесь просто необходимо
  • 34. Что в Ruby хорошо? • Писать DSL • Сам язык очень выразительный • Код приятно писать и читать • И на этом все :(
  • 35. Решились писать Enterprise на Rails? • Нужен ли Вам Rails? Может, достаточно взять Sinatra + Grape, если у вас будет SPA (Single Page Application)? • Тщательно обрабатывайте требования. Выясняйте Use Cases- • На основании UseCases стройте доменную модель (набор классов и их взаимодействия). • Не привязывайтесь к ActiveRecord. ActiveRecord - только для представления данных! • Тщательно выбирайте гемы. Подумайте 100500 раз прежде чем выбрать InheritedResources, например. • Следуйте принципам SOLID, не нарушайте закон Деметры
  • 36. Литература 1. http://goo.gl/GyqjXg - 7 steps to get started with Clean Architecture in Ruby 2. http://goo.gl/g0VA1 - 7 Patterns to Refactor Fat ActiveRecord Models 3. http://goo.gl/lz1fEX - Ruby Midwest 2011 - Keynote: Architecture the Lost Years by Robert Martin 4. http://goo.gl/MP6L7Z - High-Low Testing 5. http://goo.gl/aI3kdc - Growing Rails Applications in Practice 6. http://goo.gl/9KsmM - Принципы проектирования классов (S.O.L.I.D.)
  • 37. На правах рекламы ! Основы Rake Простые примеры применения в реальном мире Сравнение с конкурентом - Thor
  • 38. Вопросы? Андрей Колешко @ka8725- ka8725@gmail.com