SlideShare a Scribd company logo
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

More Related Content

PDF
Извлечение информации из веб-страниц - Михаил Коробов, PyCon RU 2014
PDF
М. Коробов "Машинное обучение на фронте и в тылу", DUMP-2014
PDF
2017-03-26 03 Илья Сиганов. Что такое машинное обучение
PDF
Ibne maryam - ابن مریم
PPTX
Simple present for schedules
PPTX
英语魔方秀English mofunshow
PDF
Modul lengkap
Извлечение информации из веб-страниц - Михаил Коробов, PyCon RU 2014
М. Коробов "Машинное обучение на фронте и в тылу", DUMP-2014
2017-03-26 03 Илья Сиганов. Что такое машинное обучение
Ibne maryam - ابن مریم
Simple present for schedules
英语魔方秀English mofunshow
Modul lengkap

Viewers also liked (20)

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

Similar to Rom - Ruby Object Mapper (20)

ODP
Rom и его составляющие
PDF
Ror - The Beginning
PDF
Why Ruby?
PDF
Aleksey Mashanov Rit
PDF
Aleksey Mashanov Rit
PDF
Anton Tsitou "Cycle ORM and Graphs"
PPTX
Object-Relational Mapping for Dummies
PPT
Контент ориентированное программирование
PDF
Корпоративное приложение на Rails
KEY
Sequel — механизм доступа к БД, написанный на Ruby
PPT
Catalyst and Rose::DB
PPT
Rose::DB
PDF
Презентация Neo4j на ADD-3
PDF
Гатиятов Руслан, технический директор ООО “Дроид Лабс”: “Система управления п...
PDF
Евгений Лазин. Неизменяемая структура данных HAMT для создания БД в памяти
PDF
Purely practical data structures
ODP
Alexander Dymo - IT-клуб Николаева - April 2011 - Ruby: Beaty and the Beast
PPT
Rupyru2007 Rastyagaev Ruby
PDF
Nosql and Mongodb
PPTX
Cassandra
Rom и его составляющие
Ror - The Beginning
Why Ruby?
Aleksey Mashanov Rit
Aleksey Mashanov Rit
Anton Tsitou "Cycle ORM and Graphs"
Object-Relational Mapping for Dummies
Контент ориентированное программирование
Корпоративное приложение на Rails
Sequel — механизм доступа к БД, написанный на Ruby
Catalyst and Rose::DB
Rose::DB
Презентация Neo4j на ADD-3
Гатиятов Руслан, технический директор ООО “Дроид Лабс”: “Система управления п...
Евгений Лазин. Неизменяемая структура данных HAMT для создания БД в памяти
Purely practical data structures
Alexander Dymo - IT-клуб Николаева - April 2011 - Ruby: Beaty and the Beast
Rupyru2007 Rastyagaev Ruby
Nosql and Mongodb
Cassandra
Ad

More from Alexander Kirillov (9)

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

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