SlideShare a Scribd company logo
Me
Nikita Shilnikov
• github.com/flash-gordon
• Whatever developer
• dry-rb and rom-rb core team member
ROM
disinterring the stewardess
Ruby Object Mapper
ROM vs ORM
ROM vs AR
ROM vs AR
user = Users.create(name: 'John Doe')
user.age = 30
user.save
ROM vs AR
builder = SqlBuilder.new <<-SQL
UPDATE topic_users tu
SET notification_level =
CASE WHEN should_track THEN :tracking
WHEN should_watch THEN :watching
ELSE notification_level
END,
notifications_reason_id =
CASE WHEN should_track THEN null
WHEN should_watch THEN :auto_watch_category
ELSE notifications_reason_id
END
FROM (
SELECT tu1.topic_id,
tu1.user_id,
CASE WHEN
cu.user_id IS NULL AND tu1.notification_level = :watching AND tu1.notifications_reason_id = :auto_watch_category THEN true
ELSE false
END should_track,
CASE WHEN
cu.user_id IS NOT NULL AND tu1.notification_level in (:regular, :tracking) THEN true
ELSE false
END should_watch
FROM topic_users tu1
JOIN topics t ON t.id = tu1.topic_id
LEFT JOIN category_users cu ON cu.category_id = t.category_id AND cu.user_id = tu1.user_id AND cu.notification_level = :watching
/*where2*/
) as X
/*where*/
SQL
ROM vs AR
--builder = SqlBuilder.new <<-SQL
UPDATE topic_users tu
SET notification_level =
CASE WHEN should_track THEN :tracking
WHEN should_watch THEN :watching
ELSE notification_level
END,
notifications_reason_id =
CASE WHEN should_track THEN null
WHEN should_watch THEN :auto_watch_category
ELSE notifications_reason_id
END
FROM (
SELECT tu1.topic_id,
tu1.user_id,
CASE WHEN
cu.user_id IS NULL AND tu1.notification_level = :watching AND tu1.notifications_reason_id = :auto_watch_category THEN true
ELSE false
END should_track,
CASE WHEN
cu.user_id IS NOT NULL AND tu1.notification_level in (:regular, :tracking) THEN true
ELSE false
END should_watch
FROM topic_users tu1
JOIN topics t ON t.id = tu1.topic_id
LEFT JOIN category_users cu ON cu.category_id = t.category_id AND cu.user_id = tu1.user_id AND cu.notification_level = :watching
/*where2*/
) as X
/*where*/
SQL
Ac#veRecord is not your Domain Layer
Code is not data
Data is $$$
Code is !
Code is live
Data is not
Filling the gap
Use your database
ROM
Ideology
• No global state
• Immutability
• Explicitness
• Leverage your database
• CQRS
Overview
Overview
Gems
• rom – core facili-es
• rom-sql – RDBMS interac-on
• rom-repository – applica-on-level interface
Rela%on
• Reads data
• Adapter-specific
Rela%ons
class Users < ROM::Relation[:sql]
schema(infer: true)
end
Rela%on
class Users < ROM::Relation[:sql]
schema do
attribute :id, Types::Serial
attribute :name, Types::String
end
end
Rela%on
class Users < ROM::Relation[:sql]
schema(infer: true)
def by_name(name)
where(name: name)
end
end
Command
• Writes data
• Bound to rela0on
Command
class CreateUser < ROM::Commands::Create[:sql]
relation :users
register_as :create
result :one
end
Container !
rela%ons + commands + DB connec%ons
Container !
rom = ROM.container(:sql, 'sqlite::memory')
Repository
• Accesses applica+on data
• Receives a container
Repository
(ROM::Repository::Root.instance_methods - Object.new.methods).size # => 12
(ROM::Repository::Root.methods - Class.new.methods).size # => 9
Repository
(ROM::Repository::Root.instance_methods - Object.new.methods).size # => 12
(ROM::Repository::Root.methods - Class.new.methods).size # => 9
(ApplicationRecord.instance_methods - Object.new.methods).size
(ApplicationRecord.methods - Class.new.methods).size
Repository
(ROM::Repository::Root.instance_methods - Object.new.methods).size # => 12
(ROM::Repository::Root.methods - Class.new.methods).size # => 9
(ApplicationRecord.instance_methods - Object.new.methods).size # => 244
(ApplicationRecord.methods - Class.new.methods).size # => 467
TOTAL # => 711
Repository
class UserRepo < ROM::Repository[:users]
end
Repository
class UserRepo < ROM::Repository[:users]
def list
users.order(:name).to_a
end
end
Repository
repo = UserRepo.new(rom)
repo.list # => [#<ROM::Struct[User] id=1 name="Jane">]
Changeset
changeset = repo.changeset(name: 'John')
changeset.map(:add_timestamps).to_h
# => {:name=>"John",
# :created_at=>2017-03-18 16:33:19 +0300,
# :updated_at=>2017-03-18 16:33:19 +0300}
repo.create(changeset.map(:add_timestamps))
Changeset
changeset = repo.changeset(user.id, name: 'John Doe')
changeset.diff? # => true
changeset.diff # => {:name=>'John Doe'}
To the cool stuff! !
No global state
Many containers
Many containers
rom = ROM.container(:sql, DB_URL)
rom_replica = ROM.container(:sql, DB_REPLICA_URL)
repo = UserRepo.new(rom)
read_only_repo = UserRepo.new(rom_replica)
Many adapters
rom = ROM.container(
default: [:sql, 'postgres://localhost/rom_repository'],
cache: [:sql, 'sqlite::memory']
) do |c|
c.gateways[:cache].create_table :counters do
primary_key :id
column :user_id, Integer
column :type, String
column :value, Integer
end
end
Many adapters
rom = ROM.container(
default: [:sql, 'postgres://localhost/rom_repository'],
cache: [:sql, 'sqlite::memory']
) do |c|
c.gateways[:cache].create_table :counters do
primary_key :id
column :user_id, Integer
column :type, String
column :value, Integer
end
c.relation(:users) do
schema(infer: true)
end
end
Many adapters
rom = ROM.container(
default: [:sql, 'postgres://localhost/rom_repository'],
cache: [:sql, 'sqlite::memory']
) do |c|
c.gateways[:cache].create_table :counters do
primary_key :id
column :user_id, Integer
column :type, String
column :value, Integer
end
c.relation(:users) do
schema(infer: true)
end
c.relation(:counters) do
gateway :cache
schema(infer: true)
def for_users(users)
where(user_id: users.pluck(:id))
end
end
end
Many adapters
class UserRepo < ROM::Repository[:users]
relations :counters
end
repo = UserRepo.new(rom)
Many adapters
repo.
users.
combine(many: {
counters: [repo.counters.for_users, id: :user_id]
}).
where { id <= 2 }.
to_a
=begin
[
#<ROM::Struct[User] id=1 name="Jane" counters=[
#<ROM::Struct[Counter] id=1 user_id=1 type="posts" value=3>,
#<ROM::Struct[Counter] id=2 user_id=1 type="comments" value=512>
]>,
#<ROM::Struct[User] id=2 name="Joe" counters=[]>
]
=end
No N+1!
I, [2017-03-18T19:37:14 #6638] (0.000765s) SELECT "id", "name" FROM "users" WHERE ("id" <= 2) ORDER BY "users"."id"
I, [2017-03-18T19:37:14 #6638] (0.000172s) SELECT `id`, `user_id`, `type`, `value` FROM `counters` WHERE (`user_id` IN (1, 2)) ORDER BY `counters`.`id`
One database
repo.aggregate(:counters).where { id <= 2 }.to_a
Moar backends
• rom-yaml
• rom-h*p
• rom-mongo
• rom-couchdb
• rom-ka3a
• rom-redis
• rom-git
Plans
ROM 4.0 roadmap
• More powerful mapping facili2es
• Cross-adapter associa2ons
• Move a bunch of features from rom-repository to rom-core
• Auto-migra2ons in rom-sql ✨
Help
• Give it a try
• Use different adapters
• Docs
• Contribute
Spasibo

More Related Content

What's hot

Config Management with MicroOperators
Config Management with MicroOperatorsConfig Management with MicroOperators
Config Management with MicroOperators
QAware GmbH
 
Ruby HTTP clients
Ruby HTTP clientsRuby HTTP clients
Ruby HTTP clients
Zoran Majstorovic
 
Using Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databasesUsing Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databasesRaimonds Simanovskis
 
Laravel5 Introduction and essentials
Laravel5 Introduction and essentialsLaravel5 Introduction and essentials
Laravel5 Introduction and essentials
Pramod Kadam
 
Php classes in mumbai
Php classes in mumbaiPhp classes in mumbai
Php classes in mumbai
aadi Surve
 
Rush, a shell that will yield to you
Rush, a shell that will yield to youRush, a shell that will yield to you
Rush, a shell that will yield to you
guestdd9d06
 
Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.
Visual Engineering
 
Painless Data Storage with MongoDB & Go
Painless Data Storage with MongoDB & Go Painless Data Storage with MongoDB & Go
Painless Data Storage with MongoDB & Go
Steven Francia
 
Mini Rails Framework
Mini Rails FrameworkMini Rails Framework
Mini Rails Framework
Aviandri Rivai
 
Basic command ppt
Basic command pptBasic command ppt
Basic command pptRohit Kumar
 
2. writing MySql plugins general
2. writing MySql plugins   general2. writing MySql plugins   general
2. writing MySql plugins generalRoland Bouman
 
Vidoop CouchDB Talk
Vidoop CouchDB TalkVidoop CouchDB Talk
Vidoop CouchDB Talk
Chris Anderson
 
Basic linux commands
Basic linux commandsBasic linux commands
Basic linux commands
Dheeraj Nambiar
 
React for Beginners
React for BeginnersReact for Beginners
React for Beginners
Derek Willian Stavis
 
The new features of PHP 7
The new features of PHP 7The new features of PHP 7
The new features of PHP 7
Zend by Rogue Wave Software
 
DSLs Internas e Ruby
DSLs Internas e RubyDSLs Internas e Ruby
DSLs Internas e Ruby
Fabio Kung
 
Example Stream Setup
Example  Stream  SetupExample  Stream  Setup
Example Stream Setup
cfministries
 
Logrotate sh
Logrotate shLogrotate sh
Logrotate sh
Ben Pope
 

What's hot (20)

Config Management with MicroOperators
Config Management with MicroOperatorsConfig Management with MicroOperators
Config Management with MicroOperators
 
Ruby HTTP clients
Ruby HTTP clientsRuby HTTP clients
Ruby HTTP clients
 
Using Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databasesUsing Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databases
 
Laravel5 Introduction and essentials
Laravel5 Introduction and essentialsLaravel5 Introduction and essentials
Laravel5 Introduction and essentials
 
Php classes in mumbai
Php classes in mumbaiPhp classes in mumbai
Php classes in mumbai
 
Rush, a shell that will yield to you
Rush, a shell that will yield to youRush, a shell that will yield to you
Rush, a shell that will yield to you
 
Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.
 
Unix - Shell Scripts
Unix - Shell ScriptsUnix - Shell Scripts
Unix - Shell Scripts
 
tools
toolstools
tools
 
Painless Data Storage with MongoDB & Go
Painless Data Storage with MongoDB & Go Painless Data Storage with MongoDB & Go
Painless Data Storage with MongoDB & Go
 
Mini Rails Framework
Mini Rails FrameworkMini Rails Framework
Mini Rails Framework
 
Basic command ppt
Basic command pptBasic command ppt
Basic command ppt
 
2. writing MySql plugins general
2. writing MySql plugins   general2. writing MySql plugins   general
2. writing MySql plugins general
 
Vidoop CouchDB Talk
Vidoop CouchDB TalkVidoop CouchDB Talk
Vidoop CouchDB Talk
 
Basic linux commands
Basic linux commandsBasic linux commands
Basic linux commands
 
React for Beginners
React for BeginnersReact for Beginners
React for Beginners
 
The new features of PHP 7
The new features of PHP 7The new features of PHP 7
The new features of PHP 7
 
DSLs Internas e Ruby
DSLs Internas e RubyDSLs Internas e Ruby
DSLs Internas e Ruby
 
Example Stream Setup
Example  Stream  SetupExample  Stream  Setup
Example Stream Setup
 
Logrotate sh
Logrotate shLogrotate sh
Logrotate sh
 

Similar to Ruby meetup ROM

HES2011 - joernchen - Ruby on Rails from a Code Auditor Perspective
HES2011 - joernchen - Ruby on Rails from a Code Auditor PerspectiveHES2011 - joernchen - Ruby on Rails from a Code Auditor Perspective
HES2011 - joernchen - Ruby on Rails from a Code Auditor PerspectiveHackito Ergo Sum
 
Intro To Node.js
Intro To Node.jsIntro To Node.js
Intro To Node.js
Chris Cowan
 
Rails web api 开发
Rails web api 开发Rails web api 开发
Rails web api 开发
shaokun
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
sickill
 
Rack
RackRack
Rack
shen liu
 
Learning to code for startup mvp session 3
Learning to code for startup mvp session 3Learning to code for startup mvp session 3
Learning to code for startup mvp session 3Henry S
 
Some tips to improve developer experience with Symfony
Some tips to improve developer experience with SymfonySome tips to improve developer experience with Symfony
Some tips to improve developer experience with Symfony
tyomo4ka
 
Tools and Tips for Moodle Developers - #mootus16
 Tools and Tips for Moodle Developers - #mootus16 Tools and Tips for Moodle Developers - #mootus16
Tools and Tips for Moodle Developers - #mootus16
Dan Poltawski
 
Ruby meetup-dry
Ruby meetup-dryRuby meetup-dry
Ruby meetup-dry
Nikita Shilnikov
 
How to Make Android's Bootable Recovery Work For You by Drew Suarez
How to Make Android's Bootable Recovery Work For You by Drew SuarezHow to Make Android's Bootable Recovery Work For You by Drew Suarez
How to Make Android's Bootable Recovery Work For You by Drew Suarez
Shakacon
 
Docker
DockerDocker
Docker
Chen Chun
 
Intro to node and mongodb 1
Intro to node and mongodb   1Intro to node and mongodb   1
Intro to node and mongodb 1Mohammad Qureshi
 
REST APIs in Laravel 101
REST APIs in Laravel 101REST APIs in Laravel 101
REST APIs in Laravel 101
Samantha Geitz
 
C++ in kernel mode
C++ in kernel modeC++ in kernel mode
C++ in kernel mode
corehard_by
 
Introduction to Laravel Framework (5.2)
Introduction to Laravel Framework (5.2)Introduction to Laravel Framework (5.2)
Introduction to Laravel Framework (5.2)
Viral Solani
 
Rack is Spectacular
Rack is SpectacularRack is Spectacular
Rack is Spectacular
Bryce Kerley
 
Ruby on Rails Presentation
Ruby on Rails PresentationRuby on Rails Presentation
Ruby on Rails Presentation
Michael MacDonald
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiRan Mizrahi
 

Similar to Ruby meetup ROM (20)

HES2011 - joernchen - Ruby on Rails from a Code Auditor Perspective
HES2011 - joernchen - Ruby on Rails from a Code Auditor PerspectiveHES2011 - joernchen - Ruby on Rails from a Code Auditor Perspective
HES2011 - joernchen - Ruby on Rails from a Code Auditor Perspective
 
Intro To Node.js
Intro To Node.jsIntro To Node.js
Intro To Node.js
 
Rails web api 开发
Rails web api 开发Rails web api 开发
Rails web api 开发
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
 
Rack
RackRack
Rack
 
Learning to code for startup mvp session 3
Learning to code for startup mvp session 3Learning to code for startup mvp session 3
Learning to code for startup mvp session 3
 
Some tips to improve developer experience with Symfony
Some tips to improve developer experience with SymfonySome tips to improve developer experience with Symfony
Some tips to improve developer experience with Symfony
 
Tools and Tips for Moodle Developers - #mootus16
 Tools and Tips for Moodle Developers - #mootus16 Tools and Tips for Moodle Developers - #mootus16
Tools and Tips for Moodle Developers - #mootus16
 
Ruby meetup-dry
Ruby meetup-dryRuby meetup-dry
Ruby meetup-dry
 
Rails 4.0
Rails 4.0Rails 4.0
Rails 4.0
 
How to Make Android's Bootable Recovery Work For You by Drew Suarez
How to Make Android's Bootable Recovery Work For You by Drew SuarezHow to Make Android's Bootable Recovery Work For You by Drew Suarez
How to Make Android's Bootable Recovery Work For You by Drew Suarez
 
Docker
DockerDocker
Docker
 
Intro to node and mongodb 1
Intro to node and mongodb   1Intro to node and mongodb   1
Intro to node and mongodb 1
 
REST APIs in Laravel 101
REST APIs in Laravel 101REST APIs in Laravel 101
REST APIs in Laravel 101
 
C++ in kernel mode
C++ in kernel modeC++ in kernel mode
C++ in kernel mode
 
Introduction to Laravel Framework (5.2)
Introduction to Laravel Framework (5.2)Introduction to Laravel Framework (5.2)
Introduction to Laravel Framework (5.2)
 
Rack is Spectacular
Rack is SpectacularRack is Spectacular
Rack is Spectacular
 
Ruby on Rails Presentation
Ruby on Rails PresentationRuby on Rails Presentation
Ruby on Rails Presentation
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran Mizrahi
 
Capistrano Overview
Capistrano OverviewCapistrano Overview
Capistrano Overview
 

Recently uploaded

Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
DianaGray10
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
SOFTTECHHUB
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
Adtran
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 
A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...
sonjaschweigert1
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
Quotidiano Piemontese
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
Alex Pruden
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
Neo4j
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
Matthew Sinclair
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
Matthew Sinclair
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
RinaMondal9
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
名前 です男
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
Kari Kakkonen
 

Recently uploaded (20)

Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 
A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
 

Ruby meetup ROM

  • 1.
  • 2. Me Nikita Shilnikov • github.com/flash-gordon • Whatever developer • dry-rb and rom-rb core team member
  • 4.
  • 8. ROM vs AR user = Users.create(name: 'John Doe') user.age = 30 user.save
  • 9. ROM vs AR builder = SqlBuilder.new <<-SQL UPDATE topic_users tu SET notification_level = CASE WHEN should_track THEN :tracking WHEN should_watch THEN :watching ELSE notification_level END, notifications_reason_id = CASE WHEN should_track THEN null WHEN should_watch THEN :auto_watch_category ELSE notifications_reason_id END FROM ( SELECT tu1.topic_id, tu1.user_id, CASE WHEN cu.user_id IS NULL AND tu1.notification_level = :watching AND tu1.notifications_reason_id = :auto_watch_category THEN true ELSE false END should_track, CASE WHEN cu.user_id IS NOT NULL AND tu1.notification_level in (:regular, :tracking) THEN true ELSE false END should_watch FROM topic_users tu1 JOIN topics t ON t.id = tu1.topic_id LEFT JOIN category_users cu ON cu.category_id = t.category_id AND cu.user_id = tu1.user_id AND cu.notification_level = :watching /*where2*/ ) as X /*where*/ SQL
  • 10. ROM vs AR --builder = SqlBuilder.new <<-SQL UPDATE topic_users tu SET notification_level = CASE WHEN should_track THEN :tracking WHEN should_watch THEN :watching ELSE notification_level END, notifications_reason_id = CASE WHEN should_track THEN null WHEN should_watch THEN :auto_watch_category ELSE notifications_reason_id END FROM ( SELECT tu1.topic_id, tu1.user_id, CASE WHEN cu.user_id IS NULL AND tu1.notification_level = :watching AND tu1.notifications_reason_id = :auto_watch_category THEN true ELSE false END should_track, CASE WHEN cu.user_id IS NOT NULL AND tu1.notification_level in (:regular, :tracking) THEN true ELSE false END should_watch FROM topic_users tu1 JOIN topics t ON t.id = tu1.topic_id LEFT JOIN category_users cu ON cu.category_id = t.category_id AND cu.user_id = tu1.user_id AND cu.notification_level = :watching /*where2*/ ) as X /*where*/ SQL
  • 11.
  • 12.
  • 13. Ac#veRecord is not your Domain Layer
  • 14. Code is not data
  • 20. ROM
  • 21.
  • 22.
  • 23. Ideology • No global state • Immutability • Explicitness • Leverage your database • CQRS
  • 26. Gems • rom – core facili-es • rom-sql – RDBMS interac-on • rom-repository – applica-on-level interface
  • 27. Rela%on • Reads data • Adapter-specific
  • 28. Rela%ons class Users < ROM::Relation[:sql] schema(infer: true) end
  • 29. Rela%on class Users < ROM::Relation[:sql] schema do attribute :id, Types::Serial attribute :name, Types::String end end
  • 30. Rela%on class Users < ROM::Relation[:sql] schema(infer: true) def by_name(name) where(name: name) end end
  • 31. Command • Writes data • Bound to rela0on
  • 32. Command class CreateUser < ROM::Commands::Create[:sql] relation :users register_as :create result :one end
  • 33. Container ! rela%ons + commands + DB connec%ons
  • 34. Container ! rom = ROM.container(:sql, 'sqlite::memory')
  • 35. Repository • Accesses applica+on data • Receives a container
  • 36. Repository (ROM::Repository::Root.instance_methods - Object.new.methods).size # => 12 (ROM::Repository::Root.methods - Class.new.methods).size # => 9
  • 37. Repository (ROM::Repository::Root.instance_methods - Object.new.methods).size # => 12 (ROM::Repository::Root.methods - Class.new.methods).size # => 9 (ApplicationRecord.instance_methods - Object.new.methods).size (ApplicationRecord.methods - Class.new.methods).size
  • 38. Repository (ROM::Repository::Root.instance_methods - Object.new.methods).size # => 12 (ROM::Repository::Root.methods - Class.new.methods).size # => 9 (ApplicationRecord.instance_methods - Object.new.methods).size # => 244 (ApplicationRecord.methods - Class.new.methods).size # => 467 TOTAL # => 711
  • 39. Repository class UserRepo < ROM::Repository[:users] end
  • 40. Repository class UserRepo < ROM::Repository[:users] def list users.order(:name).to_a end end
  • 41. Repository repo = UserRepo.new(rom) repo.list # => [#<ROM::Struct[User] id=1 name="Jane">]
  • 42. Changeset changeset = repo.changeset(name: 'John') changeset.map(:add_timestamps).to_h # => {:name=>"John", # :created_at=>2017-03-18 16:33:19 +0300, # :updated_at=>2017-03-18 16:33:19 +0300} repo.create(changeset.map(:add_timestamps))
  • 43. Changeset changeset = repo.changeset(user.id, name: 'John Doe') changeset.diff? # => true changeset.diff # => {:name=>'John Doe'}
  • 44. To the cool stuff! !
  • 47. Many containers rom = ROM.container(:sql, DB_URL) rom_replica = ROM.container(:sql, DB_REPLICA_URL) repo = UserRepo.new(rom) read_only_repo = UserRepo.new(rom_replica)
  • 48. Many adapters rom = ROM.container( default: [:sql, 'postgres://localhost/rom_repository'], cache: [:sql, 'sqlite::memory'] ) do |c| c.gateways[:cache].create_table :counters do primary_key :id column :user_id, Integer column :type, String column :value, Integer end end
  • 49. Many adapters rom = ROM.container( default: [:sql, 'postgres://localhost/rom_repository'], cache: [:sql, 'sqlite::memory'] ) do |c| c.gateways[:cache].create_table :counters do primary_key :id column :user_id, Integer column :type, String column :value, Integer end c.relation(:users) do schema(infer: true) end end
  • 50. Many adapters rom = ROM.container( default: [:sql, 'postgres://localhost/rom_repository'], cache: [:sql, 'sqlite::memory'] ) do |c| c.gateways[:cache].create_table :counters do primary_key :id column :user_id, Integer column :type, String column :value, Integer end c.relation(:users) do schema(infer: true) end c.relation(:counters) do gateway :cache schema(infer: true) def for_users(users) where(user_id: users.pluck(:id)) end end end
  • 51. Many adapters class UserRepo < ROM::Repository[:users] relations :counters end repo = UserRepo.new(rom)
  • 52. Many adapters repo. users. combine(many: { counters: [repo.counters.for_users, id: :user_id] }). where { id <= 2 }. to_a =begin [ #<ROM::Struct[User] id=1 name="Jane" counters=[ #<ROM::Struct[Counter] id=1 user_id=1 type="posts" value=3>, #<ROM::Struct[Counter] id=2 user_id=1 type="comments" value=512> ]>, #<ROM::Struct[User] id=2 name="Joe" counters=[]> ] =end
  • 53. No N+1! I, [2017-03-18T19:37:14 #6638] (0.000765s) SELECT "id", "name" FROM "users" WHERE ("id" <= 2) ORDER BY "users"."id" I, [2017-03-18T19:37:14 #6638] (0.000172s) SELECT `id`, `user_id`, `type`, `value` FROM `counters` WHERE (`user_id` IN (1, 2)) ORDER BY `counters`.`id`
  • 55. Moar backends • rom-yaml • rom-h*p • rom-mongo • rom-couchdb • rom-ka3a • rom-redis • rom-git
  • 56. Plans ROM 4.0 roadmap • More powerful mapping facili2es • Cross-adapter associa2ons • Move a bunch of features from rom-repository to rom-core • Auto-migra2ons in rom-sql ✨
  • 57. Help • Give it a try • Use different adapters • Docs • Contribute