Active Record • Simple pattern • Designed for simple use cases when business logic is not complex (ie CRUD) • No separation between persistence and domain objects • 1:1 mapping between db schema and domain objects Monday, October 1, 12
Data Mapper • Advanced system implementing various patterns (Mapper, Unit of Work, Repository) • Strict separation between persistence and domain logic • Designed for cases where mixing persistence concerns with domain logic becomes a problem Monday, October 1, 12
• Persistence • Validations • Life cycle hooks • Typecasting • Mass-assignment security • ...and much much more! ActiveRecord in Rails Monday, October 1, 12
Domain Model class User attr_reader :id, :name, :age def initialize(attributes) @id, @name, @age = attributes.values_at(:id, :name, :age) end # business logic goes here :) end Monday, October 1, 12
Domain Model require './user' require 'rspec' describe User do subject { User.new(id: 1, name: 'Jane', age: 21) } describe '#name' do its(:name) { should eql('Jane') } end describe '#age' do its(:age) { should eql(21) } end end Monday, October 1, 12
Mapper class User attr_reader :id, :name, :age def initialize(attributes) @id, @name, @age = attributes.values_at(:id, :name, :age) end # business logic goes here :) end Monday, October 1, 12
Mapper class User include DataMapper::Model attribute :id, Integer attribute :name, String attribute :age, Integer end DataMapper.generate_mapper_for(User) do key :id map :name, :to => :username end Monday, October 1, 12
Mapper class Address include DataMapper::Model attribute :id, Integer attribute :street, String attribute :city, String attribute :zipcode, String end class User include DataMapper::Model attribute :id, Integer attribute :name, String attribute :age, Integer attribute :address, Address end Monday, October 1, 12
Mapper class Address include DataMapper::Model attribute :id, Integer attribute :street, String attribute :city, String attribute :zipcode, String end class User include DataMapper::Model attribute :id, Integer attribute :name, String attribute :age, Integer attribute :address, Address end a user has an address Monday, October 1, 12
Mapper DataMapper.generate_mapper_for(Address) do key :id end DataMapper.generate_mapper_for(User) do key :id map :name, :to => :username has 1, :address, Address end Monday, October 1, 12
Mapper DataMapper.generate_mapper_for(Address) do key :id end DataMapper.generate_mapper_for(User) do key :id map :name, :to => :username has 1, :address, Address end OneToOne Relationship Monday, October 1, 12
Mapper class Order include DataMapper::Model attribute :id, Integer attribute :product, String end class User include DataMapper::Model attribute :id, Integer attribute :name, String attribute :age, Integer attribute :orders, Array[Order] end Monday, October 1, 12
Mapper class Order include DataMapper::Model attribute :id, Integer attribute :product, String end class User include DataMapper::Model attribute :id, Integer attribute :name, String attribute :age, Integer attribute :orders, Array[Order] end a user has orders Monday, October 1, 12
Mapper DataMapper.generate_mapper_for(Order) do key :id end DataMapper.generate_mapper_for(User) do key :id map :name, :to => :username has 0..n, :orders, Order end DataMapper[User].include(:orders).all Monday, October 1, 12
Mapper DataMapper.generate_mapper_for(Order) do key :id end DataMapper.generate_mapper_for(User) do key :id map :name, :to => :username has 0..n, :orders, Order end DataMapper[User].include(:orders).all OneToMany Relationship Monday, October 1, 12
Session DataMapper.session do |session| user = User.new(name: 'Piotr', age: 28) session.persisted?(user) # => false session.insert(user) session.commit end is the user persisted? Monday, October 1, 12
Session DataMapper.session do |session| user = User.new(name: 'Piotr', age: 28) session.persisted?(user) # => false session.insert(user) session.commit end queue the user to be persisted Monday, October 1, 12
Session DataMapper.session do |session| user = User.new(name: 'Piotr', age: 28) session.persisted?(user) # => false session.insert(user) session.commit end write changes to the database Monday, October 1, 12
Session DataMapper.session do |session| user = session[User].get(1) user.age = 29 session.dirty?(user) # => true session.update(user) session.commit end fetch the user and track it Monday, October 1, 12
Session DataMapper.session do |session| user = session[User].get(1) user.age = 29 session.dirty?(user) # => true session.update(user) session.commit end was the user changed? Monday, October 1, 12
Session DataMapper.session do |session| user = session[User].get(1) user.age = 29 session.dirty?(user) # => true session.update(user) session.commit end update the user in the database Monday, October 1, 12
Session DataMapper.session do |session| user = User.new(name: 'Piotr', age: 28) address = Address.new( street: 'Street 1', city: 'Krakow', zipcode: '12345' ) user.address = address session.insert(user) session.commit end assign the address to the user Monday, October 1, 12
Session DataMapper.session do |session| user = User.new(name: 'Piotr', age: 28) address = Address.new( street: 'Street 1', city: 'Krakow', zipcode: '12345' ) user.address = address session.insert(user) session.commit end queue the user to be persisted Monday, October 1, 12
Veritas • Created by Dan Kubb in 2010 • Complete support for all relational algebra operations • All operations can be run in-memory • Can be extended to support any kind of a datastore • Can be used with multiple different databases Monday, October 1, 12
Repository class User include DataMapper::Model attribute :id, Integer attribute :name, String attribute :age, Integer end DataMapper.generate_mapper_for(User) do key :id map :name, :to => :username end Monday, October 1, 12