SlideShare a Scribd company logo
1 of 78
Download to read offline
DataMapper als
Alternative zu
ActiveRecord ?
  Rails-Konferenz.de 2009
 Hussein Morsy & Tanja Otto



                              1
SalesLentz::DevTeam




                      2
Über uns

# internes Entwicklerteam von Sales-Lentz
# IBEs für Reisen, Bustickets, Eventtickets
# seit 2006 entwickeln wir mit Ruby on Rails
# Buch Ruby on Rails 2 Galileo Press
# http://railsbuch.de
# http://twitter.com/ajnato
# http://twitter.com/HusseinMorsy


                                                    3
Wer ist ein Rails Newbie ?




                             4
Dan Kubb – Ruby Hero




                       5
Wer setzt DataMapper ein ?




                             6
Intro




        7
ActiveRecord                                                     Intro
require 'rubygems'
require 'active_record'

ActiveRecord::Base.establish_connection(:adapter => "sqlite3",
                                        :database => "db/shop.sqlite3")

# Tabelle manuell oder per Migration erstellen

# CREATE TABLE shoes (
# ...
# );

class Shoe < ActiveRecord::Base
end

Shoe.create(:brand => "Geox", :price => 52.5)

puts Shoe.first.brand
# => Geox




                                                                          8
DataMapper                                                Intro
require 'rubygems'
require 'dm-core'
DataMapper.setup(:default, "sqlite3://db/shop.sqlite3")

class Shoe
  include DataMapper::Resource

  property   :id,          Serial
  property   :brand,       String
  property   :price,       Float
  property   :available,   Boolean
end

Shoe.auto_migrate!

Shoe.create(:brand => "Geox", :price => 52.5)

puts Shoe.first.brand
# => Geox




                                                                  9
Migrations




             10
ActiveRecord                                  Migrations
# Neue Tabelle erstellen

class CreateShoes < ActiveRecord::Migration
  def self.up
    create_table :shoes do |t|
      t.string :brand
      t.float :price

      t.timestamps
    end
  end

  def self.down
    drop_table :shoes
  end
end

rake db:migrate




                                                           11
ActiveRecord                                          Migrations
# Neues Feld hinzufügen

class AddAvailableToShoes < ActiveRecord::Migration
  def self.up
    add_column :shoes, :available, :boolean
  end

  def self.down
    remove_column :shoes, :available
  end
end

rake db:migrate




                                                                   12
DataMapper                                             Migrations
# Neue Tabelle erstellen

class Shoe
  include DataMapper::Resource

      property :id,        Serial
      property :brand,     String
      property :price,     Float
end

# Tabelle shoes erstellen
# Vorsicht: Daten gehen verloren
Shoe.auto_migrate!

# alle Tabellen erstellen
# Vorsicht: Daten gehen verloren
DataMapper.auto_migrate!

# In Datamapper gibt es auch Migrations, ähnlich wie in ActiveRecord
# siehe dm-migrations


                                                                       13
DataMapper                               Migrations
# Neues Feld hinzufügen

class Shoe
  include DataMapper::Resource

      property   :id,          Serial
      property   :brand,       String
      property   :price,       Float
      property   :available,   Boolean
end

# Vorsicht: Daten gehen verloren
Shoe.auto_migrate!




                                                      14
Extended Types




                 15
DataMapper                                     Extended Types
require 'rubygems'
require 'dm-core'
# erweiterte Datentypen
require 'dm-types'
class Shoe
  include DataMapper::Resource
  # primitive Datentypen
  # ...
  # erweiterte Datentypen
  property :color,       Enum[:red, :green, :blue]
  property :image_path, FilePath
end

shoe = Shoe.new
shoe.color = :red
shoe.image_path = "/images/shoes.jpg"
shoe.image_path.class
# => Pathname
shoe.image_path.basename
# => shoes.jpg


                                                                16
ActiveRecord       Extended Types




               ?
                                    17
Defaults




           18
ActiveRecord                                  Defaults
# Neue Tabelle erstellen

class CreateShoes < ActiveRecord::Migration
  def self.up
    create_table :shoes do |t|
      t.string :brand
      t.float :price
      t.float :tax, :default => 19.0

      t.timestamps
    end
  end

  def self.down
    drop_table :shoes
  end
end

rake db:migrate




                                                         19
DataMapper                                                   Defaults
  # Dynamische Default-Werte

  class Shoe
    include DataMapper::Resource

         property :id,         Serial
         property :brand,      String
         property :price,      Float
      property :tax,        Float, :default => 19.0
end

DataMapper.auto_migrate!

my_shoe = Shoe.create(:brand    => "demo", :price => 99.9)
puts my_shoe.tax
# => 19.0




                                                                        20
DataMapper                                   Dynamic Defaults
# Dynamische Default-Werte

class Shoe
  include DataMapper::Resource

      property   :id,      Serial
      property   :brand,   String
      property   :price,   Float
      property   :tax,     Float,   :default => 19
      property   :sale,    Float,   :default =>
                                         Proc.new { |r, p| r.price * 0.5 }
end

DataMapper.auto_migrate!

my_shoe = Shoe.create(:brand     => "demo", :price => 99.9)
puts my_shoe.sale
# => 49.95




                                                                             21
ActiveRecord       Dynamic Defaults




               ?
                                      22
Validations




              23
ActiveRecord                       Validations
# Model ohne Validierung

class Woman < ActiveRecord::Base
end




                                                 24
ActiveRecord                                          Validations
# Model mit Validierung

class Woman < ActiveRecord::Base
  validates_presence_of :name
  validates_length_of :title, :within => 2..20
  validates_format_of :email,
                      :with => /^([^@s]+)@((?:[-a-z0-9]+.)+[a-z]{2,})$/i
  validates_uniqueness_of :email
end




                                                                             25
DataMapper                       Validations
# Model ohne Validierung

class Woman
  include DataMapper::Resource

 property   :id,       Serial
 property   :name,     String
 property   :title,    String
 property   :email,    String

end




                                               26
DataMapper                                              Validations
# Model mit Validierung

class Woman
  include DataMapper::Resource

 property   :id,          Serial
 property   :name,        String, :nullable => false
 property   :title,       String, :length => 2..20
 property   :email,       String, :nullable => false,
                                  :format => :email_address,
                                  :unique => true

end




                                                                      27
Identity Map




               28
ActiveRecord                 Identity Map
Shoe.first.eql? Shoe.first

# => false




                                            29
DataMapper                   Identity Map
Shoe.first.eql? Shoe.first

# => true




                                            30
Lazy Loading




               31
DataMapper                                             Lazy Loading
class Shoe
  include DataMapper::Resource

  property   :id,                  Serial
  property   :brand,               String
  property   :price,               Float
  property   :short_description,   String, :length => 255, :lazy => true
  property   :description,         Text # default :lazy => true
end

# SELECT id, brand, price from shoes where id=1
my_shoe = Shoe.get(1)

# SELECT short_description from shoes where id=1
my_shoe.short_description

# SELECT description from shoes where id=1
my_shoe.description




                                                                           32
DataMapper                                             Lazy Loading
class Shoe
  include DataMapper::Resource

  property   :id,                  Serial
  property   :brand,               String
  property   :price,               Float
  property   :short_description,   String, :length => 255, :lazy => [:details]
  property   :description,         Text,   :lazy => [:details]
end

# SELECT id, brand, price from shoes where id=1
my_shoe = Shoe.get(1)

# SELECT short_description,description from shoes where id=1
my_shoe.short_description

# Keine Datenbankabfrage
my_shoe.description




                                                                                 33
ActiveRecord       Lazy Loading




               ?
                                  34
ActiveRecord                                       Lazy Loading
class Shoe < ActiveRecord::Base
end

my_shoe = Shoe.all(:select => "id, brand, price").first
puts my_shoe.brand

my_shoe.description
# => Exception

puts Shoe.first(:select => "id,description")




                                                                  35
Keys




       36
ActiveRecord                              Keys
# Primary Keys automatisch in Migration
# Immer Integer




                                                 37
DataMapper                                     Keys
class Woman
  include DataMapper::Resource

      property :id, Integer, :serial => true
      # ...
end

Woman.get(7)




                                                      38
DataMapper                       Keys
# Kurzform

class Woman
  include DataMapper::Resource

      property :id, Serial
      # ...
end

Woman.get(7)




                                        39
DataMapper                                               Keys
# Natürlicher Key

class Woman
  include DataMapper::Resource

  property :steuer_identifikationsnummer, :key => true
end

Woman.get("i2930d980324")




                                                                40
DataMapper                                               Keys
# Composite Keys

class Woman
  include DataMapper::Resource

  property :steuer_identifikationsnummer, :key => true
  property :pass_nr,                      :key => true
end

Woman.get("i2930d980324","949823902-X-234s")




                                                                41
Search




         42
ActiveRecord                                                   Search
class Shoe < ActiveRecord::Base
end

# the ActiveRecord-SQL-Style
Shoe.find(:all, :conditions => ["brand=? AND price < ?", "Geox", 130.0])

# brand = Geox
Shoe.all(:conditions => {:brand => "Geox"})

# brand != Geox
Shoe.all(:conditions => ["brand IS NOT ?", "Geox"])

# brand IS NOT NULL
Shoe.all(:conditions => "brand IS NOT NULL")

# brand like "G%"
Shoe.all(:conditions => "brand LIKE G%")

# brand = "Geox" OR brand= "Converse"
Shoe.all(:conditions => {:brand => ["Geox", "Converse"]})


                                                                           43
DataMapper                                                     Search
class Shoe
  include DataMapper::Resource

      property :id,        Serial
      property :brand,     String
      property :price,     Float
end

DataMapper.auto_migrate!

# the ActiveRecord-SQL-Style
Shoe.all(:conditions => ["brand=? AND price < ?", "Geox", 130.0])




                                                                        44
DataMapper                                                     Search
# the ActiveRecord-SQL-Style
Shoe.all(:conditions => ["brand=? AND price < ?", "Geox", 130.0])

# the DataMapper-Style
Shoe.all(:brand => "Geox", :price.lt => 130.0)

# brand != Geox
Shoe.all(:brand.not => "Geox")

# brand IS NOT NULL
Shoe.all(:brand.not => nil)

# brand like "G%"
Shoe.all(:brand.like => "G%")

# price <= 60.0
Shoe.all(:price.lte => 60.0)

# brand = "Geox" OR brand= "Converse"
Shoe.all(:brand => ["Geox", "Converse"])


                                                                        45
Named Scope




              46
ActiveRecord                                     Named Scope
class Shoe < ActiveRecord::Base
  named_scope :available, :conditions => ['available = ?', true]
  named_scope :cheaper,
       lambda { |max_price| { :conditions => ['price < ?', max_price] } }
end

Shoe.available.cheaper(20)




                                                                            47
DataMapper                               Named Scope
class Shoe
  include DataMapper::Resource

      property   :id,          Serial
      property   :brand,       String
      property   :price,       Float
      property   :available,   Boolean

      def self.available
       all(:available => true)
      end

      def self.cheaper(max_price)
        all(:price.lt => max_price)
      end
end

Shoe.available.cheaper(210.0)




                                                       48
Associations




               49
ActiveRecord                                       Associations
class Woman
  has_many :shoes
end

class Shoe
  belongs_to :woman
  has_many :categories, :through => :categorisations
end




                                                                  50
DataMapper                                          Associations
class Woman
  include DataMapper::Resource
  property :id,         Serial
  property :name,       String
  has n, :shoes
end

class Shoe
  include DataMapper::Resource
  property :id,         Serial
  property :brand,      String
  property :price,      Float
  property :woman_id,   Integer

  belongs_to :woman
  has n,:categories, :through => :categorisations
end




                                                                   51
Timestamps




             52
ActiveRecord                                         Timestamps
# Neue Tabelle erstellen mit einer Migration
class CreateShoes < ActiveRecord::Migration
  def self.up
    create_table :shoes do |t|
      t.string :brand
      t.float :price

     t.timestamps
   end
 end

  def self.down
    drop_table :shoes
  end
end

# Model
class Shoe < ActiveRecord::Base
end

my_shoe = Shoe.create(:brand   => "demo", :price => 99.9)
puts my_shoe.created_at
puts my_shoe.updated_at



                                                                  53
DataMapper                                             Timestamps
require 'initdb'

class Shoe
  include DataMapper::Resource

   property   :id,           Serial
   property   :brand,        String
   property   :price,        Float
   property   :created_at,   DateTime
   property   :updated_at,   DateTime
end

DataMapper.auto_migrate!

my_shoe = Shoe.create(:brand     => "demo", :price => 99.9)
puts my_shoe.created_at
# => nil




                                                                    54
DataMapper                                         Timestamps
require 'initdb'
require 'dm-timestamps'

class Shoe
  include DataMapper::Resource

   property   :id,           Serial
   property   :title,        String
   property   :price,        Float
   property   :created_at,   DateTime
   property   :updated_at,   DateTime
end

DataMapper.auto_migrate!

my_shoe = Shoe.create(:title => "demo", :price => 99.9)
puts my_shoe.created_at
# => 2009-08-30T04:29:36+00:00




                                                                55
DataMapper                                         Timestamps
require 'initdb'
require 'dm-timestamps'

class Shoe
  include DataMapper::Resource

  property :id,             Serial
  property :title,          String
  property :price,          Float

      timestamps :created_at, :updated_at
end

DataMapper.auto_migrate!

my_shoe = Shoe.create(:title => "demo", :price => 99.9)
puts my_shoe.created_at
# => 2009-08-30T04:29:36+00:00




                                                                56
DataMapper                                         Timestamps
require 'initdb'
require 'dm-timestamps'

class Shoe
  include DataMapper::Resource

  property :id,            Serial
  property :title,         String
  property :price,         Float

      timestamps :at
end

DataMapper.auto_migrate!

my_shoe = Shoe.create(:title => "demo", :price => 99.9)
puts my_shoe.created_at
# => 2009-08-30T04:29:36+00:00




                                                                57
Multi Databases




                  58
ActiveRecord       Multi Databases




               ?
                                     59
DataMapper                                   Multi Databases
DataMapper.setup(:default, "sqlite3:///#{Dir.pwd}/db/crm.sqlite3")
DataMapper.setup(:shop, "sqlite3:///#{Dir.pwd}/db/shop.sqlite3")

class Woman
  include DataMapper::Resource
  property :id,         Serial
  property :name,       String
end

class Shoe
  include DataMapper::Resource
  def self.default_repository_name
    :shop
  end

  property :id,         Serial
  property :brand,      String
  property :price,      Float

end


                                                                     60
Naming Conventions




                     61
ActiveRecord                       Naming Conventions
class Shoe < ActiveRecord::Base
  set_table_name "tbl_Shoe"
end

class Woman < ActiveRecord::Base
  set_table_name "tbl_Woman"
end




                                                        62
DataMapper                          Naming Conventions
class Shoe
  include DataMapper::Resource
  storage_names[:default] = 'tbl_Shoe'
  #....
end

class Woman
  include DataMapper::Resource
  storage_names[:default] = 'tbl_Woman'
  #....
end




                                                         63
DataMapper                          Naming Conventions
repository(:default).adapter.resource_naming_convention =
  lambda { |klass| "tbl_#{klass.camel_case}" }

class Shoe
  include DataMapper::Resource
  # ....
end

class Woman
  include DataMapper::Resource
  #....
end




                                                            64
Legacy Databases




                   65
ActiveRecord       Legacy Databases




               ?
                                      66
DataMapper                                     Legacy Databases
class Woman
  include DataMapper::Resource
  storage_names[:default] = 'tbl_woman'

  property   :id,          String,   :field => "NR", :key => true
  property   :firstname,   String,   :field => "VORNAME"
  property   :title,       String,   :field => "ANREDE"
  property   :email,       String,   :nullable => false,
                                     :format => :email_address, :unique => true
end

# Im Gegensatz zu ActiveRecord werden nur die angegebenen Felder gelesen




                                                                                  67
Adapter




          68
ActiveRecord                Adapter


                MySQL

               PostgreSQL


                 SQLite


                 Oracle


                                      69
DataMapper                 Adapter


  MySQL      YAML   IMAP   ...

PostgreSQL


  SQLite


  Oracle



                                     70
Rails 3




          71
Fazit




        72
one more thing...




                    73
74
Solo Division Winner: Jacques Crocker




                                        75
mit DataMapper gemacht!




                          76
http://github.com/merbjedi/alertme_tv




                                        77
78

More Related Content

What's hot

Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009Fabio Akita
 
Drupal7 theming-cheatsheet 0
Drupal7 theming-cheatsheet 0Drupal7 theming-cheatsheet 0
Drupal7 theming-cheatsheet 0Herbert Balagtas
 
Implementation of EAV pattern for ActiveRecord models
Implementation of EAV pattern for ActiveRecord modelsImplementation of EAV pattern for ActiveRecord models
Implementation of EAV pattern for ActiveRecord modelsKostyantyn Stepanyuk
 
EAV Sytem- Magento EAV Model
EAV Sytem- Magento EAV ModelEAV Sytem- Magento EAV Model
EAV Sytem- Magento EAV ModelKhoa Truong Dinh
 
Advanced geoprocessing with Python
Advanced geoprocessing with PythonAdvanced geoprocessing with Python
Advanced geoprocessing with PythonChad Cooper
 
Where's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsWhere's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsEleanor McHugh
 
The City Bars App with Sencha Touch 2
The City Bars App with Sencha Touch 2The City Bars App with Sencha Touch 2
The City Bars App with Sencha Touch 2James Pearce
 
Type safe embedded domain-specific languages
Type safe embedded domain-specific languagesType safe embedded domain-specific languages
Type safe embedded domain-specific languagesArthur Xavier
 
Personalized Search on the Largest Flash Sale Site in America
Personalized Search on the Largest Flash Sale Site in AmericaPersonalized Search on the Largest Flash Sale Site in America
Personalized Search on the Largest Flash Sale Site in AmericaAdrian Trenaman
 
rails-migrations_1
rails-migrations_1rails-migrations_1
rails-migrations_1brecke
 

What's hot (11)

Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009
 
Drupal7 theming-cheatsheet 0
Drupal7 theming-cheatsheet 0Drupal7 theming-cheatsheet 0
Drupal7 theming-cheatsheet 0
 
Implementation of EAV pattern for ActiveRecord models
Implementation of EAV pattern for ActiveRecord modelsImplementation of EAV pattern for ActiveRecord models
Implementation of EAV pattern for ActiveRecord models
 
Sql Antipatterns Strike Back
Sql Antipatterns Strike BackSql Antipatterns Strike Back
Sql Antipatterns Strike Back
 
EAV Sytem- Magento EAV Model
EAV Sytem- Magento EAV ModelEAV Sytem- Magento EAV Model
EAV Sytem- Magento EAV Model
 
Advanced geoprocessing with Python
Advanced geoprocessing with PythonAdvanced geoprocessing with Python
Advanced geoprocessing with Python
 
Where's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsWhere's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord Migrations
 
The City Bars App with Sencha Touch 2
The City Bars App with Sencha Touch 2The City Bars App with Sencha Touch 2
The City Bars App with Sencha Touch 2
 
Type safe embedded domain-specific languages
Type safe embedded domain-specific languagesType safe embedded domain-specific languages
Type safe embedded domain-specific languages
 
Personalized Search on the Largest Flash Sale Site in America
Personalized Search on the Largest Flash Sale Site in AmericaPersonalized Search on the Largest Flash Sale Site in America
Personalized Search on the Largest Flash Sale Site in America
 
rails-migrations_1
rails-migrations_1rails-migrations_1
rails-migrations_1
 

Similar to DataMapper as an Alternative to ActiveRecord

Say Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererSay Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererRuby Meditation
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsMike Subelsky
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Railsrstankov
 
sfDay Cologne - Sonata Admin Bundle
sfDay Cologne - Sonata Admin BundlesfDay Cologne - Sonata Admin Bundle
sfDay Cologne - Sonata Admin Bundleth0masr
 
Design Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron PattersonDesign Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron PattersonManageIQ
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
 
Your own (little) gem: building an online business with Ruby
Your own (little) gem: building an online business with RubyYour own (little) gem: building an online business with Ruby
Your own (little) gem: building an online business with RubyLindsay Holmwood
 
Intro to Rails ActiveRecord
Intro to Rails ActiveRecordIntro to Rails ActiveRecord
Intro to Rails ActiveRecordMark Menard
 
wwc start-launched
wwc start-launchedwwc start-launched
wwc start-launchedMat Schaffer
 
Building an api using golang and postgre sql v1.0
Building an api using golang and postgre sql v1.0Building an api using golang and postgre sql v1.0
Building an api using golang and postgre sql v1.0Frost
 
DSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic modelDSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic modelDebasish Ghosh
 
Acceptance Testing with Webrat
Acceptance Testing with WebratAcceptance Testing with Webrat
Acceptance Testing with WebratLuismi Cavallé
 
Rails for Beginners - Le Wagon
Rails for Beginners - Le WagonRails for Beginners - Le Wagon
Rails for Beginners - Le WagonAlex Benoit
 
RoR 101: Session 2
RoR 101: Session 2RoR 101: Session 2
RoR 101: Session 2Rory Gianni
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - IntroductionVagmi Mudumbai
 
Pourquoi ruby et rails déchirent
Pourquoi ruby et rails déchirentPourquoi ruby et rails déchirent
Pourquoi ruby et rails déchirentNicolas Ledez
 
performance vamos dormir mais?
performance vamos dormir mais?performance vamos dormir mais?
performance vamos dormir mais?tdc-globalcode
 

Similar to DataMapper as an Alternative to ActiveRecord (20)

DataMapper
DataMapperDataMapper
DataMapper
 
Say Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererSay Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick Sutterer
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
sfDay Cologne - Sonata Admin Bundle
sfDay Cologne - Sonata Admin BundlesfDay Cologne - Sonata Admin Bundle
sfDay Cologne - Sonata Admin Bundle
 
Design Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron PattersonDesign Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron Patterson
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
Your own (little) gem: building an online business with Ruby
Your own (little) gem: building an online business with RubyYour own (little) gem: building an online business with Ruby
Your own (little) gem: building an online business with Ruby
 
Intro to Rails ActiveRecord
Intro to Rails ActiveRecordIntro to Rails ActiveRecord
Intro to Rails ActiveRecord
 
wwc start-launched
wwc start-launchedwwc start-launched
wwc start-launched
 
Building an api using golang and postgre sql v1.0
Building an api using golang and postgre sql v1.0Building an api using golang and postgre sql v1.0
Building an api using golang and postgre sql v1.0
 
DSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic modelDSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic model
 
SOLID Ruby SOLID Rails
SOLID Ruby SOLID RailsSOLID Ruby SOLID Rails
SOLID Ruby SOLID Rails
 
SOLID Ruby, SOLID Rails
SOLID Ruby, SOLID RailsSOLID Ruby, SOLID Rails
SOLID Ruby, SOLID Rails
 
Acceptance Testing with Webrat
Acceptance Testing with WebratAcceptance Testing with Webrat
Acceptance Testing with Webrat
 
Rails for Beginners - Le Wagon
Rails for Beginners - Le WagonRails for Beginners - Le Wagon
Rails for Beginners - Le Wagon
 
RoR 101: Session 2
RoR 101: Session 2RoR 101: Session 2
RoR 101: Session 2
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - Introduction
 
Pourquoi ruby et rails déchirent
Pourquoi ruby et rails déchirentPourquoi ruby et rails déchirent
Pourquoi ruby et rails déchirent
 
performance vamos dormir mais?
performance vamos dormir mais?performance vamos dormir mais?
performance vamos dormir mais?
 

More from Hussein Morsy

Rubymotion trip to inspect 2013
Rubymotion trip to inspect 2013Rubymotion trip to inspect 2013
Rubymotion trip to inspect 2013Hussein Morsy
 
Unobtrusive JavaScript in Rails 3
Unobtrusive JavaScript in Rails 3Unobtrusive JavaScript in Rails 3
Unobtrusive JavaScript in Rails 3Hussein Morsy
 
Agile Softwareentwicklung mit Rails
Agile Softwareentwicklung mit RailsAgile Softwareentwicklung mit Rails
Agile Softwareentwicklung mit RailsHussein Morsy
 
Einführung in Cucumber mit Rails
Einführung in Cucumber mit RailsEinführung in Cucumber mit Rails
Einführung in Cucumber mit RailsHussein Morsy
 

More from Hussein Morsy (6)

Rubymotion trip to inspect 2013
Rubymotion trip to inspect 2013Rubymotion trip to inspect 2013
Rubymotion trip to inspect 2013
 
Unobtrusive JavaScript in Rails 3
Unobtrusive JavaScript in Rails 3Unobtrusive JavaScript in Rails 3
Unobtrusive JavaScript in Rails 3
 
Rack-Middleware
Rack-MiddlewareRack-Middleware
Rack-Middleware
 
Homebrew
HomebrewHomebrew
Homebrew
 
Agile Softwareentwicklung mit Rails
Agile Softwareentwicklung mit RailsAgile Softwareentwicklung mit Rails
Agile Softwareentwicklung mit Rails
 
Einführung in Cucumber mit Rails
Einführung in Cucumber mit RailsEinführung in Cucumber mit Rails
Einführung in Cucumber mit Rails
 

DataMapper as an Alternative to ActiveRecord

  • 1. DataMapper als Alternative zu ActiveRecord ? Rails-Konferenz.de 2009 Hussein Morsy & Tanja Otto 1
  • 3. Über uns # internes Entwicklerteam von Sales-Lentz # IBEs für Reisen, Bustickets, Eventtickets # seit 2006 entwickeln wir mit Ruby on Rails # Buch Ruby on Rails 2 Galileo Press # http://railsbuch.de # http://twitter.com/ajnato # http://twitter.com/HusseinMorsy 3
  • 4. Wer ist ein Rails Newbie ? 4
  • 5. Dan Kubb – Ruby Hero 5
  • 7. Intro 7
  • 8. ActiveRecord Intro require 'rubygems' require 'active_record' ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => "db/shop.sqlite3") # Tabelle manuell oder per Migration erstellen # CREATE TABLE shoes ( # ... # ); class Shoe < ActiveRecord::Base end Shoe.create(:brand => "Geox", :price => 52.5) puts Shoe.first.brand # => Geox 8
  • 9. DataMapper Intro require 'rubygems' require 'dm-core' DataMapper.setup(:default, "sqlite3://db/shop.sqlite3") class Shoe include DataMapper::Resource property :id, Serial property :brand, String property :price, Float property :available, Boolean end Shoe.auto_migrate! Shoe.create(:brand => "Geox", :price => 52.5) puts Shoe.first.brand # => Geox 9
  • 11. ActiveRecord Migrations # Neue Tabelle erstellen class CreateShoes < ActiveRecord::Migration def self.up create_table :shoes do |t| t.string :brand t.float :price t.timestamps end end def self.down drop_table :shoes end end rake db:migrate 11
  • 12. ActiveRecord Migrations # Neues Feld hinzufügen class AddAvailableToShoes < ActiveRecord::Migration def self.up add_column :shoes, :available, :boolean end def self.down remove_column :shoes, :available end end rake db:migrate 12
  • 13. DataMapper Migrations # Neue Tabelle erstellen class Shoe include DataMapper::Resource property :id, Serial property :brand, String property :price, Float end # Tabelle shoes erstellen # Vorsicht: Daten gehen verloren Shoe.auto_migrate! # alle Tabellen erstellen # Vorsicht: Daten gehen verloren DataMapper.auto_migrate! # In Datamapper gibt es auch Migrations, ähnlich wie in ActiveRecord # siehe dm-migrations 13
  • 14. DataMapper Migrations # Neues Feld hinzufügen class Shoe include DataMapper::Resource property :id, Serial property :brand, String property :price, Float property :available, Boolean end # Vorsicht: Daten gehen verloren Shoe.auto_migrate! 14
  • 16. DataMapper Extended Types require 'rubygems' require 'dm-core' # erweiterte Datentypen require 'dm-types' class Shoe include DataMapper::Resource # primitive Datentypen # ... # erweiterte Datentypen property :color, Enum[:red, :green, :blue] property :image_path, FilePath end shoe = Shoe.new shoe.color = :red shoe.image_path = "/images/shoes.jpg" shoe.image_path.class # => Pathname shoe.image_path.basename # => shoes.jpg 16
  • 17. ActiveRecord Extended Types ? 17
  • 18. Defaults 18
  • 19. ActiveRecord Defaults # Neue Tabelle erstellen class CreateShoes < ActiveRecord::Migration def self.up create_table :shoes do |t| t.string :brand t.float :price t.float :tax, :default => 19.0 t.timestamps end end def self.down drop_table :shoes end end rake db:migrate 19
  • 20. DataMapper Defaults # Dynamische Default-Werte class Shoe include DataMapper::Resource property :id, Serial property :brand, String property :price, Float property :tax, Float, :default => 19.0 end DataMapper.auto_migrate! my_shoe = Shoe.create(:brand => "demo", :price => 99.9) puts my_shoe.tax # => 19.0 20
  • 21. DataMapper Dynamic Defaults # Dynamische Default-Werte class Shoe include DataMapper::Resource property :id, Serial property :brand, String property :price, Float property :tax, Float, :default => 19 property :sale, Float, :default => Proc.new { |r, p| r.price * 0.5 } end DataMapper.auto_migrate! my_shoe = Shoe.create(:brand => "demo", :price => 99.9) puts my_shoe.sale # => 49.95 21
  • 22. ActiveRecord Dynamic Defaults ? 22
  • 24. ActiveRecord Validations # Model ohne Validierung class Woman < ActiveRecord::Base end 24
  • 25. ActiveRecord Validations # Model mit Validierung class Woman < ActiveRecord::Base validates_presence_of :name validates_length_of :title, :within => 2..20 validates_format_of :email, :with => /^([^@s]+)@((?:[-a-z0-9]+.)+[a-z]{2,})$/i validates_uniqueness_of :email end 25
  • 26. DataMapper Validations # Model ohne Validierung class Woman include DataMapper::Resource property :id, Serial property :name, String property :title, String property :email, String end 26
  • 27. DataMapper Validations # Model mit Validierung class Woman include DataMapper::Resource property :id, Serial property :name, String, :nullable => false property :title, String, :length => 2..20 property :email, String, :nullable => false, :format => :email_address, :unique => true end 27
  • 29. ActiveRecord Identity Map Shoe.first.eql? Shoe.first # => false 29
  • 30. DataMapper Identity Map Shoe.first.eql? Shoe.first # => true 30
  • 32. DataMapper Lazy Loading class Shoe include DataMapper::Resource property :id, Serial property :brand, String property :price, Float property :short_description, String, :length => 255, :lazy => true property :description, Text # default :lazy => true end # SELECT id, brand, price from shoes where id=1 my_shoe = Shoe.get(1) # SELECT short_description from shoes where id=1 my_shoe.short_description # SELECT description from shoes where id=1 my_shoe.description 32
  • 33. DataMapper Lazy Loading class Shoe include DataMapper::Resource property :id, Serial property :brand, String property :price, Float property :short_description, String, :length => 255, :lazy => [:details] property :description, Text, :lazy => [:details] end # SELECT id, brand, price from shoes where id=1 my_shoe = Shoe.get(1) # SELECT short_description,description from shoes where id=1 my_shoe.short_description # Keine Datenbankabfrage my_shoe.description 33
  • 34. ActiveRecord Lazy Loading ? 34
  • 35. ActiveRecord Lazy Loading class Shoe < ActiveRecord::Base end my_shoe = Shoe.all(:select => "id, brand, price").first puts my_shoe.brand my_shoe.description # => Exception puts Shoe.first(:select => "id,description") 35
  • 36. Keys 36
  • 37. ActiveRecord Keys # Primary Keys automatisch in Migration # Immer Integer 37
  • 38. DataMapper Keys class Woman include DataMapper::Resource property :id, Integer, :serial => true # ... end Woman.get(7) 38
  • 39. DataMapper Keys # Kurzform class Woman include DataMapper::Resource property :id, Serial # ... end Woman.get(7) 39
  • 40. DataMapper Keys # Natürlicher Key class Woman include DataMapper::Resource property :steuer_identifikationsnummer, :key => true end Woman.get("i2930d980324") 40
  • 41. DataMapper Keys # Composite Keys class Woman include DataMapper::Resource property :steuer_identifikationsnummer, :key => true property :pass_nr, :key => true end Woman.get("i2930d980324","949823902-X-234s") 41
  • 42. Search 42
  • 43. ActiveRecord Search class Shoe < ActiveRecord::Base end # the ActiveRecord-SQL-Style Shoe.find(:all, :conditions => ["brand=? AND price < ?", "Geox", 130.0]) # brand = Geox Shoe.all(:conditions => {:brand => "Geox"}) # brand != Geox Shoe.all(:conditions => ["brand IS NOT ?", "Geox"]) # brand IS NOT NULL Shoe.all(:conditions => "brand IS NOT NULL") # brand like "G%" Shoe.all(:conditions => "brand LIKE G%") # brand = "Geox" OR brand= "Converse" Shoe.all(:conditions => {:brand => ["Geox", "Converse"]}) 43
  • 44. DataMapper Search class Shoe include DataMapper::Resource property :id, Serial property :brand, String property :price, Float end DataMapper.auto_migrate! # the ActiveRecord-SQL-Style Shoe.all(:conditions => ["brand=? AND price < ?", "Geox", 130.0]) 44
  • 45. DataMapper Search # the ActiveRecord-SQL-Style Shoe.all(:conditions => ["brand=? AND price < ?", "Geox", 130.0]) # the DataMapper-Style Shoe.all(:brand => "Geox", :price.lt => 130.0) # brand != Geox Shoe.all(:brand.not => "Geox") # brand IS NOT NULL Shoe.all(:brand.not => nil) # brand like "G%" Shoe.all(:brand.like => "G%") # price <= 60.0 Shoe.all(:price.lte => 60.0) # brand = "Geox" OR brand= "Converse" Shoe.all(:brand => ["Geox", "Converse"]) 45
  • 47. ActiveRecord Named Scope class Shoe < ActiveRecord::Base named_scope :available, :conditions => ['available = ?', true] named_scope :cheaper, lambda { |max_price| { :conditions => ['price < ?', max_price] } } end Shoe.available.cheaper(20) 47
  • 48. DataMapper Named Scope class Shoe include DataMapper::Resource property :id, Serial property :brand, String property :price, Float property :available, Boolean def self.available all(:available => true) end def self.cheaper(max_price) all(:price.lt => max_price) end end Shoe.available.cheaper(210.0) 48
  • 50. ActiveRecord Associations class Woman has_many :shoes end class Shoe belongs_to :woman has_many :categories, :through => :categorisations end 50
  • 51. DataMapper Associations class Woman include DataMapper::Resource property :id, Serial property :name, String has n, :shoes end class Shoe include DataMapper::Resource property :id, Serial property :brand, String property :price, Float property :woman_id, Integer belongs_to :woman has n,:categories, :through => :categorisations end 51
  • 53. ActiveRecord Timestamps # Neue Tabelle erstellen mit einer Migration class CreateShoes < ActiveRecord::Migration def self.up create_table :shoes do |t| t.string :brand t.float :price t.timestamps end end def self.down drop_table :shoes end end # Model class Shoe < ActiveRecord::Base end my_shoe = Shoe.create(:brand => "demo", :price => 99.9) puts my_shoe.created_at puts my_shoe.updated_at 53
  • 54. DataMapper Timestamps require 'initdb' class Shoe include DataMapper::Resource property :id, Serial property :brand, String property :price, Float property :created_at, DateTime property :updated_at, DateTime end DataMapper.auto_migrate! my_shoe = Shoe.create(:brand => "demo", :price => 99.9) puts my_shoe.created_at # => nil 54
  • 55. DataMapper Timestamps require 'initdb' require 'dm-timestamps' class Shoe include DataMapper::Resource property :id, Serial property :title, String property :price, Float property :created_at, DateTime property :updated_at, DateTime end DataMapper.auto_migrate! my_shoe = Shoe.create(:title => "demo", :price => 99.9) puts my_shoe.created_at # => 2009-08-30T04:29:36+00:00 55
  • 56. DataMapper Timestamps require 'initdb' require 'dm-timestamps' class Shoe include DataMapper::Resource property :id, Serial property :title, String property :price, Float timestamps :created_at, :updated_at end DataMapper.auto_migrate! my_shoe = Shoe.create(:title => "demo", :price => 99.9) puts my_shoe.created_at # => 2009-08-30T04:29:36+00:00 56
  • 57. DataMapper Timestamps require 'initdb' require 'dm-timestamps' class Shoe include DataMapper::Resource property :id, Serial property :title, String property :price, Float timestamps :at end DataMapper.auto_migrate! my_shoe = Shoe.create(:title => "demo", :price => 99.9) puts my_shoe.created_at # => 2009-08-30T04:29:36+00:00 57
  • 59. ActiveRecord Multi Databases ? 59
  • 60. DataMapper Multi Databases DataMapper.setup(:default, "sqlite3:///#{Dir.pwd}/db/crm.sqlite3") DataMapper.setup(:shop, "sqlite3:///#{Dir.pwd}/db/shop.sqlite3") class Woman include DataMapper::Resource property :id, Serial property :name, String end class Shoe include DataMapper::Resource def self.default_repository_name :shop end property :id, Serial property :brand, String property :price, Float end 60
  • 62. ActiveRecord Naming Conventions class Shoe < ActiveRecord::Base set_table_name "tbl_Shoe" end class Woman < ActiveRecord::Base set_table_name "tbl_Woman" end 62
  • 63. DataMapper Naming Conventions class Shoe include DataMapper::Resource storage_names[:default] = 'tbl_Shoe' #.... end class Woman include DataMapper::Resource storage_names[:default] = 'tbl_Woman' #.... end 63
  • 64. DataMapper Naming Conventions repository(:default).adapter.resource_naming_convention = lambda { |klass| "tbl_#{klass.camel_case}" } class Shoe include DataMapper::Resource # .... end class Woman include DataMapper::Resource #.... end 64
  • 66. ActiveRecord Legacy Databases ? 66
  • 67. DataMapper Legacy Databases class Woman include DataMapper::Resource storage_names[:default] = 'tbl_woman' property :id, String, :field => "NR", :key => true property :firstname, String, :field => "VORNAME" property :title, String, :field => "ANREDE" property :email, String, :nullable => false, :format => :email_address, :unique => true end # Im Gegensatz zu ActiveRecord werden nur die angegebenen Felder gelesen 67
  • 68. Adapter 68
  • 69. ActiveRecord Adapter MySQL PostgreSQL SQLite Oracle 69
  • 70. DataMapper Adapter MySQL YAML IMAP ... PostgreSQL SQLite Oracle 70
  • 71. Rails 3 71
  • 72. Fazit 72
  • 74. 74
  • 75. Solo Division Winner: Jacques Crocker 75
  • 78. 78