SlideShare una empresa de Scribd logo
1 de 34
Descargar para leer sin conexión
ROM: Ruby Object Mapper. Revolution
Кириллов Александр, Evrone.
1
О чем буду рассказывать?
1. Преимущества и недостатки ActiveRecord
2. Что такое ROM
3. Философия ROM
4. Основные компоненты
5. Больше чем gem
6. Необычные кейсы применения
2
ActiveRecord
Я люблю ActiveRecord,
а вы?
3
ActiveRecord
• Хороший выбор для простой логики предметной области
• Независимость от СУБД
• Встроенная валидация
• Связи (relations)
4
ActiveRecord
...и капля дегтя
• Хороший выбор для простой логики предметной области CRUD
• Независимость от СУБД sql-only?!
• Встроенная валидация Напрямую завязана на модель
• Связи (relations) Магия :)
5
Недостатки ActiveRecord
• Нарушает SRP (Single responsibility principle)
• Нет PORO (Plain Old Ruby Object)
• 1-в-1 маппинг на колонки таблицы
• Вы всегда работаете со строкой таблицы
• Тесты тоже завязаны на базу данных
6
ROM
Ruby Object Mapper
ROM is an open-source persistence and mapping toolkit for Ruby built for
speed and simplicity
“
7
ROM: Концепции и решения
• Минимальная инфраструктура для маппинга и сохранности
• Высокоуровневые абстракции над низкоуровневыми компонентами
• Частные реализации запросов к хранилищу
• Разграничение чтения и изменения данных
• Упрощение базового хранилища (при желании)
• Слабые связи между компонентами
8
ROM: Чтение данных
9
ROM: Изменение данных
10
ROM: Adapter
• свой интефейс для каждой реализации (нет общего или базового)
• внутри себя использует Шлюзы, Наборы данных и Связи
• более высокая абстракция для relations и commands
11
ROM: Repositories
• Отдельный gem: gem install rom-repository
• Инкапсулирует доступ к объектам предметной области
• Автоматически связывает кортежи данных с объектами ROM::Struct
12
ROM: Repositories. Repository Class
class UserRepository < ROM::Repository::Base
relations :users
end
rom = ROM.finalize.env
user_repo = UserRepository.new(rom)
user_repo.users
13
ROM: Repositories. Repository Class
class UserRepository < ROM::Repository::Base
relations :users
def [](id)
users.where(id: id).one!
end
end
user_repo.users[1] # => <ROM::Struct[User] id=1 name="Jane">
14
ROM: Repositories
• ROM::Struct
• доступ к аттрибутам like Hash (по ключам)
• ... или с помощью методов
user = user_repo[1] #=> <ROM::Struct[User] id=1 name="Jane">
user[:id] # 1
user.id # 1
user.to_hash # {:id=>1, :name=>"Jane"}
15
ROM: Relations
• запросы к базам данных для использования в repository
• Представления (view)
• Поддержка составных связей
class UserRepository < ROM::Repository::Base
relations :users, :tasks
def with_tasks(id)
users.by_id(id).combine_children(many: tasks)
end
end
16
ROM: Relations. Auto-Combine
#combine_parents , #combine_children
class TaskRepository < ROM::Repository::Base
relations :users, :tasks, :tags
def with_owner_and_tags(id)
tasks
.by_id(id)
.combine_parents(one: { owner: users })
.combine_children(tags: tags)
end
end 17
ROM: Relations. Data Pipeline (>>)
class Users < ROM::Relation[:memory]
def by_name(name)
restrict(name: name)
end
end
name_list = -> users do
users.map { |user| user[:name] }
end
user_names = rom.relation(:users) >> name_list
rom.relation(:users).to_a # [{ id: 1, name: 'Joe'}]
user_names.to_a # ['Joe'] 18
ROM: Relations. Auto-curry
users_by_name = rom.relation(:users).by_name
# call later on using short `[]` syntax
users_by_name['Jane']
# or
users_by_name.('Jane')
# or more explicit and longer form
users_by_name.call('Jane')
19
ROM: Commands
• Изменение состояния
• ROM::Commands::Create
• ROM::Commands::Update
• ROM::Commands::Delete
• или специфичные для вашего адаптера
20
ROM: Commands
class CreateUser < ROM::Commands::Create[:memory]
relation :users
register_as :create
end
create_user = rom.command(:users).create
new_users = [{name: 'Joe'}, {name: 'Alex'}]
create_user.call(new_users)
21
ROM: Commands
class UpdateUser < ROM::Commands::Update[:memory]
relation :users
register_as :update
result :one
end
# Update user 1, setting `foo` to `"bar"`
rom.command(:users). update . by_id(1) .call(foo: "bar")
22
ROM: Commands.
Составные команды
Результаты одних команд можно предедавать в другие ( >> )
create_tasks = rom.command(:tasks).create
create_user = rom.command(:users).create
new_user = { name: 'Jane' }
new_tasks = [{ title: 'One' }, { title: 'Two' }]
command = create_user.
with(new_user) >> create_tasks.with(new_tasks)
command.call # creates a user, passes to create_tasks
23
ROM: Commands.
Граф комманд
Компановка вызова команд с глубокой вложенностью
user_with_tasks = { user: {id: 1, name: 'Joe', tasks: [
{title: 'Task one'}, {title: 'Task Two'}
]} }
create_user_with_tasks = rom.command([
{ user: :users }, [:create, [:tasks, [:create]]]
])
create_user_with_tasks.call(user_with_tasks) 24
ROM: Mappers
• Приведение объектов бизнес-логики к схебе базы данных
• ... и обратно
• Может использоваться с другими библиотеками
• Основные задачи:
• Переименование и фильтрация, группировка атрибутов
• Приведение типов атрибутов
• Создание агрегатов, иммутабельных объектов и др.
25
ROM: Mappers. Definition
users = ROM.env.relation(:users)
class UserAsEntity < ROM::Mapper
register_as :entity # name of the mapper
relation :users # the name of the relation
model User # the domain model to map tuples to
end
users.as(:entity).to_a
# [ <User @id=1, @name='jane', @email='jane@doo.org'>
# <User @id=2, @name='alex', @email='alex@doo.org'> ]
26
ROM: Mappers. Strategies
• Тонкий интерфейс
• нет знаний о модели предметной области
• самостоятельное инстанцирование
• Обычно - просто Hash
• Толстый интерфейс
• Глубокие знания модели
• Преинициализированные объекты
• Сложный доменный объект со связями и логикой
27
ROM: Mappers. Data Transformation
• Фильтрация атрибутов ( exclude, reject_keys )
• Переименование ( from )
• Оборачивание ( wrap, unwrap )
• Группировка ( group, ungroup )
• Сложение/вычитание fold, unfold
• Комбинирование из разных связей
• Встраивание ( embeded )
28
ROM: Mappers. Пошаговая
трансформация
class UserMapper < ROM::Mapper
relation :users
step do
group :tasks do
...
end
end
step do
... 29
ROM: Forms
class TaskForm < ROM::Model::Form
input do
set_model_name 'Task'
attribute :title, String
end
validations do
relation :tasks
validates :title, presence: true
end
end
30
Что уже есть?
• Релиз 1.0 в конце сентября
• Большое количество адаптеров
• SQL: ado, amalgalite, cubrid, db2, dbi, do, fdbsql, firebird, ibmdb,
informix, jdbc, mysql, mysql2, odbc, openbase, oracle, postgres,
sqlanywhere, sqlite, swift, tinytds
• Graphs: neo4j
• NoSQL: mongo, couchdb; KV: redis
• FileStorage: json, yml, csv; Network: http, git
31
Уже готова интеграция с
Rails, Lotus
32
Нестандартные варианты
использования
• В библиотеках
• Разнообразные источники данных
33
Вопросы?
• Подробнее об SRP:
• Patterns of Enterprise Application Architecture
by Martin Fowler
• ROM:
• http://rom-rb.org
• http://rom-rb.org/tutorials/todo-app-with-rails
• https://github.com/rom-rb
• https://twitter.com/_solnic_
34

Más contenido relacionado

Destacado

Kite introduction
Kite introductionKite introduction
Kite introductionkitehitech
 
GOD MAKES ALL THINGS BEAUTIFUL IN HIS TIME
GOD MAKES ALL THINGS BEAUTIFUL IN HIS TIMEGOD MAKES ALL THINGS BEAUTIFUL IN HIS TIME
GOD MAKES ALL THINGS BEAUTIFUL IN HIS TIMEStanley Tan
 
Karmapa visit singapore 1999 magazine 噶瑪巴駕臨新加坡特刊
Karmapa visit singapore 1999 magazine 噶瑪巴駕臨新加坡特刊Karmapa visit singapore 1999 magazine 噶瑪巴駕臨新加坡特刊
Karmapa visit singapore 1999 magazine 噶瑪巴駕臨新加坡特刊Lin Zhang Sheng
 
Merkel double wiper_pt-1
Merkel double wiper_pt-1Merkel double wiper_pt-1
Merkel double wiper_pt-1walleseals
 
BSidesNYC 2016 - An Adversarial View of SaaS Malware Sandboxes
BSidesNYC 2016 - An Adversarial View of SaaS Malware SandboxesBSidesNYC 2016 - An Adversarial View of SaaS Malware Sandboxes
BSidesNYC 2016 - An Adversarial View of SaaS Malware SandboxesJason Trost
 
演讲手势合集
演讲手势合集演讲手势合集
演讲手势合集zsk91186
 
Kode etik jurnalistik ifj penafsiran dan praktik
Kode etik jurnalistik ifj penafsiran dan praktikKode etik jurnalistik ifj penafsiran dan praktik
Kode etik jurnalistik ifj penafsiran dan praktikTeras Lampung
 
Crear Unha Conta Gmail
Crear Unha Conta GmailCrear Unha Conta Gmail
Crear Unha Conta Gmailvicente
 
Recursos procesales civiles hector oberg yañez
Recursos procesales civiles hector  oberg  yañezRecursos procesales civiles hector  oberg  yañez
Recursos procesales civiles hector oberg yañezCarlos Cruz
 
Anyone Can Cook Report - WOWEL
Anyone Can Cook Report - WOWELAnyone Can Cook Report - WOWEL
Anyone Can Cook Report - WOWELyoonsukim1110
 
รายชื่อคณะทำงาน
รายชื่อคณะทำงานรายชื่อคณะทำงาน
รายชื่อคณะทำงานsongdet khunta
 

Destacado (20)

Kite introduction
Kite introductionKite introduction
Kite introduction
 
GOD MAKES ALL THINGS BEAUTIFUL IN HIS TIME
GOD MAKES ALL THINGS BEAUTIFUL IN HIS TIMEGOD MAKES ALL THINGS BEAUTIFUL IN HIS TIME
GOD MAKES ALL THINGS BEAUTIFUL IN HIS TIME
 
Karmapa visit singapore 1999 magazine 噶瑪巴駕臨新加坡特刊
Karmapa visit singapore 1999 magazine 噶瑪巴駕臨新加坡特刊Karmapa visit singapore 1999 magazine 噶瑪巴駕臨新加坡特刊
Karmapa visit singapore 1999 magazine 噶瑪巴駕臨新加坡特刊
 
KV Menu 6-25-2015
KV Menu 6-25-2015KV Menu 6-25-2015
KV Menu 6-25-2015
 
Merkel double wiper_pt-1
Merkel double wiper_pt-1Merkel double wiper_pt-1
Merkel double wiper_pt-1
 
BSidesNYC 2016 - An Adversarial View of SaaS Malware Sandboxes
BSidesNYC 2016 - An Adversarial View of SaaS Malware SandboxesBSidesNYC 2016 - An Adversarial View of SaaS Malware Sandboxes
BSidesNYC 2016 - An Adversarial View of SaaS Malware Sandboxes
 
演讲手势合集
演讲手势合集演讲手势合集
演讲手势合集
 
Boe February 10 2009 Agenda
Boe February 10 2009 AgendaBoe February 10 2009 Agenda
Boe February 10 2009 Agenda
 
Kode etik jurnalistik ifj penafsiran dan praktik
Kode etik jurnalistik ifj penafsiran dan praktikKode etik jurnalistik ifj penafsiran dan praktik
Kode etik jurnalistik ifj penafsiran dan praktik
 
Saz1
Saz1Saz1
Saz1
 
Final oral test
Final oral testFinal oral test
Final oral test
 
Crear Unha Conta Gmail
Crear Unha Conta GmailCrear Unha Conta Gmail
Crear Unha Conta Gmail
 
Satz1
Satz1Satz1
Satz1
 
Recursos procesales civiles hector oberg yañez
Recursos procesales civiles hector  oberg  yañezRecursos procesales civiles hector  oberg  yañez
Recursos procesales civiles hector oberg yañez
 
Elearning v.0.0
Elearning v.0.0Elearning v.0.0
Elearning v.0.0
 
Anyone Can Cook Report - WOWEL
Anyone Can Cook Report - WOWELAnyone Can Cook Report - WOWEL
Anyone Can Cook Report - WOWEL
 
รายชื่อคณะทำงาน
รายชื่อคณะทำงานรายชื่อคณะทำงาน
รายชื่อคณะทำงาน
 
Fgcfg
FgcfgFgcfg
Fgcfg
 
Trigical for Trigeminal Neuralgia Treatment
Trigical for Trigeminal Neuralgia TreatmentTrigical for Trigeminal Neuralgia Treatment
Trigical for Trigeminal Neuralgia Treatment
 
Daaaaaa
DaaaaaaDaaaaaa
Daaaaaa
 

Similar a Rom - Ruby Object Mapper

Корпоративное приложение на Rails
Корпоративное приложение на RailsКорпоративное приложение на Rails
Корпоративное приложение на RailsAndrei Kaleshka
 
CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как...
CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как...CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как...
CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как...CodeFest
 
Alexander Dymo - IT Jam 2009 - Ruby: Beaty Or The Beast
Alexander Dymo - IT Jam 2009 - Ruby: Beaty Or The BeastAlexander Dymo - IT Jam 2009 - Ruby: Beaty Or The Beast
Alexander Dymo - IT Jam 2009 - Ruby: Beaty Or The BeastAlexander Dymo
 
Юрий Буянов «Архитектура Goozy»
Юрий Буянов «Архитектура Goozy»Юрий Буянов «Архитектура Goozy»
Юрий Буянов «Архитектура Goozy»e-Legion
 
YuryByyanov (e-legion) @ CodeCamp2011
YuryByyanov (e-legion) @ CodeCamp2011YuryByyanov (e-legion) @ CodeCamp2011
YuryByyanov (e-legion) @ CodeCamp2011CodeCamp
 
CodeFest 2013. Скрыган К. — Оптимизация .Net приложений на примере Resharper
CodeFest 2013. Скрыган К. — Оптимизация .Net приложений на примере ResharperCodeFest 2013. Скрыган К. — Оптимизация .Net приложений на примере Resharper
CodeFest 2013. Скрыган К. — Оптимизация .Net приложений на примере ResharperCodeFest
 
Оптимизация производительности нагруженных веб-систем на Java
Оптимизация производительности нагруженных веб-систем на JavaОптимизация производительности нагруженных веб-систем на Java
Оптимизация производительности нагруженных веб-систем на JavaAlex Chistyakov
 
разработка бизнес приложений (7)
разработка бизнес приложений (7)разработка бизнес приложений (7)
разработка бизнес приложений (7)Alexander Gornik
 
Опыт эксплуатации большого проекта на Ruby
Опыт эксплуатации большого проекта на RubyОпыт эксплуатации большого проекта на Ruby
Опыт эксплуатации большого проекта на RubyAlex Chistyakov
 
Практическое создание крупного масштабируемого web 20 c нуля, Дмитрий Бородин
Практическое создание крупного масштабируемого web 20 c нуля, Дмитрий БородинПрактическое создание крупного масштабируемого web 20 c нуля, Дмитрий Бородин
Практическое создание крупного масштабируемого web 20 c нуля, Дмитрий БородинFuenteovejuna
 
Ruby On Rails: Web-разработка по-другому!
Ruby On Rails: Web-разработка по-другому!Ruby On Rails: Web-разработка по-другому!
Ruby On Rails: Web-разработка по-другому!Constantin Kichinsky
 
Дизайн больших приложений в ФП
Дизайн больших приложений в ФПДизайн больших приложений в ФП
Дизайн больших приложений в ФПAlexander Granin
 
разработка бизнес приложений (6)
разработка бизнес приложений (6)разработка бизнес приложений (6)
разработка бизнес приложений (6)Alexander Gornik
 
Егор Львовский — «Кеширование на клиенте и сервере»
Егор Львовский — «Кеширование на клиенте и сервере»Егор Львовский — «Кеширование на клиенте и сервере»
Егор Львовский — «Кеширование на клиенте и сервере»Yandex
 
Программирование как способ выражения мыслей.
Программирование как способ выражения мыслей. Программирование как способ выражения мыслей.
Программирование как способ выражения мыслей. Levon Avakyan
 
андрей паньгин
андрей паньгинандрей паньгин
андрей паньгинkuchinskaya
 
Hadoop presentation
Hadoop presentationHadoop presentation
Hadoop presentationVlad Orlov
 
Mihail Korepanov
Mihail KorepanovMihail Korepanov
Mihail Korepanovyaevents
 
Михаил Корепанов "Скорость рендеринга страниц: исследования, замеры, автомати...
Михаил Корепанов "Скорость рендеринга страниц: исследования, замеры, автомати...Михаил Корепанов "Скорость рендеринга страниц: исследования, замеры, автомати...
Михаил Корепанов "Скорость рендеринга страниц: исследования, замеры, автомати...Yandex
 

Similar a Rom - Ruby Object Mapper (20)

Корпоративное приложение на Rails
Корпоративное приложение на RailsКорпоративное приложение на Rails
Корпоративное приложение на Rails
 
CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как...
CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как...CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как...
CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как...
 
Alexander Dymo - IT Jam 2009 - Ruby: Beaty Or The Beast
Alexander Dymo - IT Jam 2009 - Ruby: Beaty Or The BeastAlexander Dymo - IT Jam 2009 - Ruby: Beaty Or The Beast
Alexander Dymo - IT Jam 2009 - Ruby: Beaty Or The Beast
 
Юрий Буянов «Архитектура Goozy»
Юрий Буянов «Архитектура Goozy»Юрий Буянов «Архитектура Goozy»
Юрий Буянов «Архитектура Goozy»
 
YuryByyanov (e-legion) @ CodeCamp2011
YuryByyanov (e-legion) @ CodeCamp2011YuryByyanov (e-legion) @ CodeCamp2011
YuryByyanov (e-legion) @ CodeCamp2011
 
CodeFest 2013. Скрыган К. — Оптимизация .Net приложений на примере Resharper
CodeFest 2013. Скрыган К. — Оптимизация .Net приложений на примере ResharperCodeFest 2013. Скрыган К. — Оптимизация .Net приложений на примере Resharper
CodeFest 2013. Скрыган К. — Оптимизация .Net приложений на примере Resharper
 
Оптимизация производительности нагруженных веб-систем на Java
Оптимизация производительности нагруженных веб-систем на JavaОптимизация производительности нагруженных веб-систем на Java
Оптимизация производительности нагруженных веб-систем на Java
 
разработка бизнес приложений (7)
разработка бизнес приложений (7)разработка бизнес приложений (7)
разработка бизнес приложений (7)
 
Опыт эксплуатации большого проекта на Ruby
Опыт эксплуатации большого проекта на RubyОпыт эксплуатации большого проекта на Ruby
Опыт эксплуатации большого проекта на Ruby
 
Практическое создание крупного масштабируемого web 20 c нуля, Дмитрий Бородин
Практическое создание крупного масштабируемого web 20 c нуля, Дмитрий БородинПрактическое создание крупного масштабируемого web 20 c нуля, Дмитрий Бородин
Практическое создание крупного масштабируемого web 20 c нуля, Дмитрий Бородин
 
Ruby On Rails: Web-разработка по-другому!
Ruby On Rails: Web-разработка по-другому!Ruby On Rails: Web-разработка по-другому!
Ruby On Rails: Web-разработка по-другому!
 
18.08.2012 meta ruby
18.08.2012 meta ruby18.08.2012 meta ruby
18.08.2012 meta ruby
 
Дизайн больших приложений в ФП
Дизайн больших приложений в ФПДизайн больших приложений в ФП
Дизайн больших приложений в ФП
 
разработка бизнес приложений (6)
разработка бизнес приложений (6)разработка бизнес приложений (6)
разработка бизнес приложений (6)
 
Егор Львовский — «Кеширование на клиенте и сервере»
Егор Львовский — «Кеширование на клиенте и сервере»Егор Львовский — «Кеширование на клиенте и сервере»
Егор Львовский — «Кеширование на клиенте и сервере»
 
Программирование как способ выражения мыслей.
Программирование как способ выражения мыслей. Программирование как способ выражения мыслей.
Программирование как способ выражения мыслей.
 
андрей паньгин
андрей паньгинандрей паньгин
андрей паньгин
 
Hadoop presentation
Hadoop presentationHadoop presentation
Hadoop presentation
 
Mihail Korepanov
Mihail KorepanovMihail Korepanov
Mihail Korepanov
 
Михаил Корепанов "Скорость рендеринга страниц: исследования, замеры, автомати...
Михаил Корепанов "Скорость рендеринга страниц: исследования, замеры, автомати...Михаил Корепанов "Скорость рендеринга страниц: исследования, замеры, автомати...
Михаил Корепанов "Скорость рендеринга страниц: исследования, замеры, автомати...
 

Más de Alexander Kirillov

Окружение разработчика - от виртуализации к контейнеризации
Окружение разработчика - от виртуализации к контейнеризацииОкружение разработчика - от виртуализации к контейнеризации
Окружение разработчика - от виртуализации к контейнеризацииAlexander Kirillov
 
Polymer - New Era of Web Development
Polymer - New Era of Web DevelopmentPolymer - New Era of Web Development
Polymer - New Era of Web DevelopmentAlexander Kirillov
 
Виртуализация как инструмент разработчика
Виртуализация как инструмент разработчикаВиртуализация как инструмент разработчика
Виртуализация как инструмент разработчикаAlexander Kirillov
 
Application deployment & configuration management
Application deployment & configuration managementApplication deployment & configuration management
Application deployment & configuration managementAlexander Kirillov
 
Предметно-ориентированные языки программирования (DSL)
Предметно-ориентированные языки программирования (DSL)Предметно-ориентированные языки программирования (DSL)
Предметно-ориентированные языки программирования (DSL)Alexander Kirillov
 

Más de Alexander Kirillov (9)

Окружение разработчика - от виртуализации к контейнеризации
Окружение разработчика - от виртуализации к контейнеризацииОкружение разработчика - от виртуализации к контейнеризации
Окружение разработчика - от виртуализации к контейнеризации
 
Polymer - New Era of Web Development
Polymer - New Era of Web DevelopmentPolymer - New Era of Web Development
Polymer - New Era of Web Development
 
Виртуализация как инструмент разработчика
Виртуализация как инструмент разработчикаВиртуализация как инструмент разработчика
Виртуализация как инструмент разработчика
 
Application deployment & configuration management
Application deployment & configuration managementApplication deployment & configuration management
Application deployment & configuration management
 
XSLT. Basic.
XSLT. Basic.XSLT. Basic.
XSLT. Basic.
 
Предметно-ориентированные языки программирования (DSL)
Предметно-ориентированные языки программирования (DSL)Предметно-ориентированные языки программирования (DSL)
Предметно-ориентированные языки программирования (DSL)
 
Securing Rails Applications
Securing Rails ApplicationsSecuring Rails Applications
Securing Rails Applications
 
Ruby gui
Ruby guiRuby gui
Ruby gui
 
I18n
I18nI18n
I18n
 

Rom - Ruby Object Mapper

  • 1. ROM: Ruby Object Mapper. Revolution Кириллов Александр, Evrone. 1
  • 2. О чем буду рассказывать? 1. Преимущества и недостатки ActiveRecord 2. Что такое ROM 3. Философия ROM 4. Основные компоненты 5. Больше чем gem 6. Необычные кейсы применения 2
  • 4. ActiveRecord • Хороший выбор для простой логики предметной области • Независимость от СУБД • Встроенная валидация • Связи (relations) 4
  • 5. ActiveRecord ...и капля дегтя • Хороший выбор для простой логики предметной области CRUD • Независимость от СУБД sql-only?! • Встроенная валидация Напрямую завязана на модель • Связи (relations) Магия :) 5
  • 6. Недостатки ActiveRecord • Нарушает SRP (Single responsibility principle) • Нет PORO (Plain Old Ruby Object) • 1-в-1 маппинг на колонки таблицы • Вы всегда работаете со строкой таблицы • Тесты тоже завязаны на базу данных 6
  • 7. ROM Ruby Object Mapper ROM is an open-source persistence and mapping toolkit for Ruby built for speed and simplicity “ 7
  • 8. ROM: Концепции и решения • Минимальная инфраструктура для маппинга и сохранности • Высокоуровневые абстракции над низкоуровневыми компонентами • Частные реализации запросов к хранилищу • Разграничение чтения и изменения данных • Упрощение базового хранилища (при желании) • Слабые связи между компонентами 8
  • 11. ROM: Adapter • свой интефейс для каждой реализации (нет общего или базового) • внутри себя использует Шлюзы, Наборы данных и Связи • более высокая абстракция для relations и commands 11
  • 12. ROM: Repositories • Отдельный gem: gem install rom-repository • Инкапсулирует доступ к объектам предметной области • Автоматически связывает кортежи данных с объектами ROM::Struct 12
  • 13. ROM: Repositories. Repository Class class UserRepository < ROM::Repository::Base relations :users end rom = ROM.finalize.env user_repo = UserRepository.new(rom) user_repo.users 13
  • 14. ROM: Repositories. Repository Class class UserRepository < ROM::Repository::Base relations :users def [](id) users.where(id: id).one! end end user_repo.users[1] # => <ROM::Struct[User] id=1 name="Jane"> 14
  • 15. ROM: Repositories • ROM::Struct • доступ к аттрибутам like Hash (по ключам) • ... или с помощью методов user = user_repo[1] #=> <ROM::Struct[User] id=1 name="Jane"> user[:id] # 1 user.id # 1 user.to_hash # {:id=>1, :name=>"Jane"} 15
  • 16. ROM: Relations • запросы к базам данных для использования в repository • Представления (view) • Поддержка составных связей class UserRepository < ROM::Repository::Base relations :users, :tasks def with_tasks(id) users.by_id(id).combine_children(many: tasks) end end 16
  • 17. ROM: Relations. Auto-Combine #combine_parents , #combine_children class TaskRepository < ROM::Repository::Base relations :users, :tasks, :tags def with_owner_and_tags(id) tasks .by_id(id) .combine_parents(one: { owner: users }) .combine_children(tags: tags) end end 17
  • 18. ROM: Relations. Data Pipeline (>>) class Users < ROM::Relation[:memory] def by_name(name) restrict(name: name) end end name_list = -> users do users.map { |user| user[:name] } end user_names = rom.relation(:users) >> name_list rom.relation(:users).to_a # [{ id: 1, name: 'Joe'}] user_names.to_a # ['Joe'] 18
  • 19. ROM: Relations. Auto-curry users_by_name = rom.relation(:users).by_name # call later on using short `[]` syntax users_by_name['Jane'] # or users_by_name.('Jane') # or more explicit and longer form users_by_name.call('Jane') 19
  • 20. ROM: Commands • Изменение состояния • ROM::Commands::Create • ROM::Commands::Update • ROM::Commands::Delete • или специфичные для вашего адаптера 20
  • 21. ROM: Commands class CreateUser < ROM::Commands::Create[:memory] relation :users register_as :create end create_user = rom.command(:users).create new_users = [{name: 'Joe'}, {name: 'Alex'}] create_user.call(new_users) 21
  • 22. ROM: Commands class UpdateUser < ROM::Commands::Update[:memory] relation :users register_as :update result :one end # Update user 1, setting `foo` to `"bar"` rom.command(:users). update . by_id(1) .call(foo: "bar") 22
  • 23. ROM: Commands. Составные команды Результаты одних команд можно предедавать в другие ( >> ) create_tasks = rom.command(:tasks).create create_user = rom.command(:users).create new_user = { name: 'Jane' } new_tasks = [{ title: 'One' }, { title: 'Two' }] command = create_user. with(new_user) >> create_tasks.with(new_tasks) command.call # creates a user, passes to create_tasks 23
  • 24. ROM: Commands. Граф комманд Компановка вызова команд с глубокой вложенностью user_with_tasks = { user: {id: 1, name: 'Joe', tasks: [ {title: 'Task one'}, {title: 'Task Two'} ]} } create_user_with_tasks = rom.command([ { user: :users }, [:create, [:tasks, [:create]]] ]) create_user_with_tasks.call(user_with_tasks) 24
  • 25. ROM: Mappers • Приведение объектов бизнес-логики к схебе базы данных • ... и обратно • Может использоваться с другими библиотеками • Основные задачи: • Переименование и фильтрация, группировка атрибутов • Приведение типов атрибутов • Создание агрегатов, иммутабельных объектов и др. 25
  • 26. ROM: Mappers. Definition users = ROM.env.relation(:users) class UserAsEntity < ROM::Mapper register_as :entity # name of the mapper relation :users # the name of the relation model User # the domain model to map tuples to end users.as(:entity).to_a # [ <User @id=1, @name='jane', @email='jane@doo.org'> # <User @id=2, @name='alex', @email='alex@doo.org'> ] 26
  • 27. ROM: Mappers. Strategies • Тонкий интерфейс • нет знаний о модели предметной области • самостоятельное инстанцирование • Обычно - просто Hash • Толстый интерфейс • Глубокие знания модели • Преинициализированные объекты • Сложный доменный объект со связями и логикой 27
  • 28. ROM: Mappers. Data Transformation • Фильтрация атрибутов ( exclude, reject_keys ) • Переименование ( from ) • Оборачивание ( wrap, unwrap ) • Группировка ( group, ungroup ) • Сложение/вычитание fold, unfold • Комбинирование из разных связей • Встраивание ( embeded ) 28
  • 29. ROM: Mappers. Пошаговая трансформация class UserMapper < ROM::Mapper relation :users step do group :tasks do ... end end step do ... 29
  • 30. ROM: Forms class TaskForm < ROM::Model::Form input do set_model_name 'Task' attribute :title, String end validations do relation :tasks validates :title, presence: true end end 30
  • 31. Что уже есть? • Релиз 1.0 в конце сентября • Большое количество адаптеров • SQL: ado, amalgalite, cubrid, db2, dbi, do, fdbsql, firebird, ibmdb, informix, jdbc, mysql, mysql2, odbc, openbase, oracle, postgres, sqlanywhere, sqlite, swift, tinytds • Graphs: neo4j • NoSQL: mongo, couchdb; KV: redis • FileStorage: json, yml, csv; Network: http, git 31
  • 33. Нестандартные варианты использования • В библиотеках • Разнообразные источники данных 33
  • 34. Вопросы? • Подробнее об SRP: • Patterns of Enterprise Application Architecture by Martin Fowler • ROM: • http://rom-rb.org • http://rom-rb.org/tutorials/todo-app-with-rails • https://github.com/rom-rb • https://twitter.com/_solnic_ 34