SlideShare a Scribd company logo
CAN WE STILL INNOVATE?
PIOTR SOLNICA RubyDay 2016, Florence
mojotech.com
rom-rb.org dry-rb.org
RubyDay 2016 - Can we still innovate?
2005 - 2010
RubyDay 2016 - Can we still innovate?
CONVENTION
OVER
CONFIGURATION
RubyDay 2016 - Can we still innovate?
COMPLEXITY
ᕕ(˵•̀෴•́˵)ᕗ
“FAT MODEL” WAS
AN AMBIGUOUS IDEA
EXPLORING NEW
APPROACHES…
DDD
DCI
SPFDL
(TOTALLY MADE
THIS UP)
SEPARATING PERSISTENCE
FROM DOMAIN LOGIC
MAYBE REPOSITORY
PATTERN?
MAYBE A FULL-BLOWN
DATAMAPPER PATTERN?
MEANWHILE…
NEW LIBRARIES
AND FRAMEWORKS!
RubyDay 2016 - Can we still innovate?
RubyDay 2016 - Can we still innovate?
RubyDay 2016 - Can we still innovate?
RAILS.MERGE(MERB)
2008-2010
2010+
RubyDay 2016 - Can we still innovate?
NEW ABSTRACTIONS
▸ Form objects
▸ Value objects
▸ Service objects
▸ Query objects
▸ Policy objects
▸ View objects
SPFDL
DATAMAPPER 2
VIRTUS
RubyDay 2016 - Can we still innovate?
ROM-RB.ORG
RubyDay 2016 - Can we still innovate?
2016
ROM-RB.ORG
RubyDay 2016 - Can we still innovate?
ROM-RB INNOVATIONS
▸ Read/Write separation
▸ Relations as first-class citizens
▸ Data transformations instead of object mutations
▸ Explicit relation composition instead of ambiguous query
DSLs
▸ Command API for custom db-specific database operations
▸ Externalized data validations
cfg = ROM::Configuration.new(:sql, 'sqlite::memory')
cfg.gateways[:default].create_table(:users) do
primary_key :id
column :name, String, null: false
column :age, Integer, null: true
end
cfg.gateways[:default].create_table(:tasks) do
primary_key :id
foreign_key :user_id, :users, null: false, on_delete: :cascade
column :title, String, null: true
end
class Users < ROM::Relation[:sql]
schema(infer: true)
end
class Tasks < ROM::Relation[:sql]
schema(infer: true)
end
SETS UP RELATION
ATTRIBUTES BASED ON DATABASE
SCHEMA SCHEMA
INFERS TABLE NAME FROM CLASS
NAME
rom = ROM.container(cfg)
NO GLOBAL
POLLUTION
REPOSITORIES
class UserRepo < ROM::Repository[:users]
commands :create
end
user_repo = UserRepo.new(rom)
user_repo.create(name: 'Jane', age: 33)
# => #<ROM::Struct[User] id=3 name="Jane" age=33>
CHANGESETS
class UserRepo < ROM::Repository[:users]
commands :create, update: :by_pk
end
user_repo = UserRepo.new(rom)
user = user_repo.create(name: 'Jane', age: 33)
changeset = user_repo.changeset(user.id, name: 'Jane Doe')
changeset.diff
# => {:name=>"Jane Doe"}
user_repo.update(user.id, changeset)
# => #<ROM::Struct[User] id=1 name="Jane Doe" age=33>
AGGREGATES
class Users < ROM::Relation[:sql]
schema(infer: true) do
associations do
has_many :tasks
end
end
end
class UserRepo < ROM::Repository[:users]
relations :tasks
def create_with_tasks(user)
command(:create, aggregate(:tasks)).call(user)
end
end
user_repo.aggregate(:tasks)
# [#<ROM::Struct[User] id=3 name="Jane" age=33
tasks=[#<ROM::Struct[Task] id=5 user_id=3 title="Jane task 1">,
#<ROM::Struct[Task] id=6 user_id=3 title="Jane task 2">]>>
CUSTOM OBJECTS
require 'dry-struct'
class Task < Dry::Struct
attribute :title, Types::Strict::String
end
class User < Dry::Struct
attribute :name, Types::Strict::String
attribute :age, Types::Strict::Int
attribute :tasks, Types::Strict::Array.member(Task)
end
user_repo.aggregate(:tasks).as(User).to_a
# => [#<User name="Jane" age=33 tasks=[#<Task title="Jane
task 1">, #<Task title="Jane task 2">]>, #<User
name="John" age=32 tasks=[#<Task title="John task 1">,
#<Task title="John task 2">]>]
DRY-RB.ORG
RubyDay 2016 - Can we still innovate?
DRY-RB INNOVATIONS
▸ Advanced data validation
▸ Flexible type system with coercions and constraints
▸ Composable transactions with error handling based on
monads
▸ Simple yet powerful Dependency Injection
▸ Application state management with component lifecycles
DRY-STRUCT
class User < Dry::Struct
attribute :name, Types::Strict::String
attribute :age, Types::Strict::Int
end
module Types
include Dry::Types.module
Age = Types::Strict::Int.constrained(gt: 18)
end
class User < Dry::Struct
attribute :name, Types::Strict::String
attribute :age, Types::Age
end
User.new(name: 'John', age: 17)
# [User.new] 17 (Fixnum) has invalid type for :age
(Dry::Struct::Error)
DRY-VALIDATION
VALIDATION
SCHEMAS
UserSchema = Dry::Validation.Schema do
required(:login).value(:str?, size?: 2..64)
required(:age).maybe(:int?, gt?: 18)
end
IS IT A STRING WITH A SIZE
BETWEEN 2 AND 64 CHARS?
CAN BE NIL BUT
IF IT’S NOT THEN IS IT AN
INTEGER AND IS IT GREATER
THAN 18?
UserSchema.(login: "j", age: 19).errors
# {:login=>["length must be within 2 - 64"]}
UserSchema.(login: "jane", age: nil).errors
# {}
SHORTCUT FOR `#CALL` :)
COMPOSING
SCHEMAS
AddressSchema = Dry::Validation.Schema do
required(:street).value(:str?)
required(:city).filled(:str?)
required(:zipcode).filled(:int?)
end
UserSchema = Dry::Validation.Schema do
required(:login).value(:str?, size?: 2..64)
required(:age).maybe(:int?, gt?: 18)
required(:address).schema(AddressSchema)
end
VALIDATION HINTS
UserSchema.(login: 'jane', age: 'oops').errors
# {:age=>["must be an integer"]}
UserSchema.(login: 'jane', age: 'oops').hints
# {:age=>["must be greater than 18"]}
DRY-SYSTEM
MANAGING STATE
require 'dry/system/container'
class Application < Dry::System::Container
configure do |config|
config.root = Pathname.new('./my/app')
end
end
# now you can register a logger
require 'logger'
Application.register('utils.logger', Logger.new($stdout))
# and access it
Application['utils.logger']
AUTO-
REGISTRATION
require 'dry/system/container'
class Application < Dry::System::Container
configure do |config|
config.root = '/my/app'
config.auto_register = 'lib'
end
load_paths!('lib')
end
# under /my/app/lib/logger.rb we put
class Logger
# some neat logger implementation
end
# we can finalize the container which triggers auto-registration
Application.finalize!
# the logger becomes available
Application[‘logger']
BOOTING
COMPONENTS
# system/boot/persistence.rb
Application.finalize(:persistence) do
init do
require '3rd-party/database'
end
start do
container.register('database') do
3rdParty::Database.new
end
end
stop do
container['database'].disconnect
end
end
class Application < Dry::Component::Container
configure do |config|
config.root = '/my/app'
end
end
# requires needed files and boots your persistence component
Application.boot!(:persistence)
# and now `database` becomes available
Application['database']
# lib/worker.rb
require ‘application/import'
class Worker
include Import['database']
def do_stuff
users = database.read('select * from users')
# ..
end
end
THIS WILL INJECT “DATABASE”
OBJECT AND MAKE IT AVAILABLE
2016…
LET’S CONTINUE
EXPLORING & INNOVATING
ᕦʕ ՞ ౪ ՞ ʔᕤ
THANK YOU <3

More Related Content

PDF
CSMR10b.ppt
PDF
Public Squash Foundation
DOCX
Trabajos
PDF
Resume 1
PDF
Using insights from behavioral science to break barriers to post-secundary ed...
DOCX
PR Individual
PPTX
Bab 2 Membuat Presentasi
PDF
Sistema operativo elizabeth aguilar
CSMR10b.ppt
Public Squash Foundation
Trabajos
Resume 1
Using insights from behavioral science to break barriers to post-secundary ed...
PR Individual
Bab 2 Membuat Presentasi
Sistema operativo elizabeth aguilar

Viewers also liked (12)

DOCX
Fp fm reporte aplicacion aamtic_g89_act.4-angelap.muñoz
PPTX
Gnesis Invest
PDF
Adapting a Lesson Plan
PDF
NHK WORLD
PPTX
LES TIC I LA INCLUSIÓ EDUCATIVA
PDF
Welcome To Source A Tech
PPT
Tipologies d'oci i temps lliure
PPT
La retta
PPTX
Pakuranga Library Trip
PDF
Individualni konsalting za menadžere
PPT
Napza
Fp fm reporte aplicacion aamtic_g89_act.4-angelap.muñoz
Gnesis Invest
Adapting a Lesson Plan
NHK WORLD
LES TIC I LA INCLUSIÓ EDUCATIVA
Welcome To Source A Tech
Tipologies d'oci i temps lliure
La retta
Pakuranga Library Trip
Individualni konsalting za menadžere
Napza
Ad

Similar to RubyDay 2016 - Can we still innovate? (20)

PPTX
Where are yours vertexes and what are they talking about?
PDF
JavaScript for Enterprise Applications
PDF
Exploiting the Data / Code Duality with Dali
PDF
MongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
PPTX
Offline first: application data and synchronization
PDF
AngularJS in large applications - AE NV
PPTX
Benefits of Using MongoDB Over RDBMSs
PDF
MongoDB.local Paris Keynote
PPTX
Patterns for distributed systems
PPTX
DDS Advanced Tutorial - OMG June 2013 Berlin Meeting
PDF
Node.js for enterprise - JS Conference
PDF
Vital AI MetaQL: Queries Across NoSQL, SQL, Sparql, and Spark
PDF
Intro to Databases
PPT
Gordon Semantic Web 2008
PPTX
MongoDB Schema Design: Practical Applications and Implications
PPT
Object Oriented Concepts and Principles
PDF
Labeling all the Things with the WDI Skill Labeler
PDF
Structs to JSON How Go Powers REST APIs.pdf
PPTX
Benefits of Using MongoDB Over RDBMS (At An Evening with MongoDB Minneapolis ...
PPTX
The Clean Architecture
Where are yours vertexes and what are they talking about?
JavaScript for Enterprise Applications
Exploiting the Data / Code Duality with Dali
MongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
Offline first: application data and synchronization
AngularJS in large applications - AE NV
Benefits of Using MongoDB Over RDBMSs
MongoDB.local Paris Keynote
Patterns for distributed systems
DDS Advanced Tutorial - OMG June 2013 Berlin Meeting
Node.js for enterprise - JS Conference
Vital AI MetaQL: Queries Across NoSQL, SQL, Sparql, and Spark
Intro to Databases
Gordon Semantic Web 2008
MongoDB Schema Design: Practical Applications and Implications
Object Oriented Concepts and Principles
Labeling all the Things with the WDI Skill Labeler
Structs to JSON How Go Powers REST APIs.pdf
Benefits of Using MongoDB Over RDBMS (At An Evening with MongoDB Minneapolis ...
The Clean Architecture
Ad

Recently uploaded (20)

PPTX
1. Introduction to Computer Programming.pptx
PPTX
MicrosoftCybserSecurityReferenceArchitecture-April-2025.pptx
PDF
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
PDF
Hybrid model detection and classification of lung cancer
PPTX
TLE Review Electricity (Electricity).pptx
PDF
A novel scalable deep ensemble learning framework for big data classification...
PDF
STKI Israel Market Study 2025 version august
PDF
August Patch Tuesday
PPTX
Chapter 5: Probability Theory and Statistics
PPTX
Final SEM Unit 1 for mit wpu at pune .pptx
PDF
Developing a website for English-speaking practice to English as a foreign la...
PDF
A contest of sentiment analysis: k-nearest neighbor versus neural network
PDF
Enhancing emotion recognition model for a student engagement use case through...
PDF
Getting Started with Data Integration: FME Form 101
PDF
Architecture types and enterprise applications.pdf
PPT
Module 1.ppt Iot fundamentals and Architecture
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PPTX
cloud_computing_Infrastucture_as_cloud_p
PPTX
OMC Textile Division Presentation 2021.pptx
PDF
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
1. Introduction to Computer Programming.pptx
MicrosoftCybserSecurityReferenceArchitecture-April-2025.pptx
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
Hybrid model detection and classification of lung cancer
TLE Review Electricity (Electricity).pptx
A novel scalable deep ensemble learning framework for big data classification...
STKI Israel Market Study 2025 version august
August Patch Tuesday
Chapter 5: Probability Theory and Statistics
Final SEM Unit 1 for mit wpu at pune .pptx
Developing a website for English-speaking practice to English as a foreign la...
A contest of sentiment analysis: k-nearest neighbor versus neural network
Enhancing emotion recognition model for a student engagement use case through...
Getting Started with Data Integration: FME Form 101
Architecture types and enterprise applications.pdf
Module 1.ppt Iot fundamentals and Architecture
NewMind AI Weekly Chronicles - August'25-Week II
cloud_computing_Infrastucture_as_cloud_p
OMC Textile Division Presentation 2021.pptx
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf

RubyDay 2016 - Can we still innovate?