Datamapper Railskonferenz 2009

78
DataMapper als Alternative zu ActiveRecord ? Rails-Konferenz.de 2009 Hussein Morsy & Tanja Otto 1

Transcript of Datamapper Railskonferenz 2009

Page 1: Datamapper Railskonferenz 2009

DataMapper als Alternative zuActiveRecord ?

Rails-Konferenz.de 2009Hussein Morsy & Tanja Otto

1

Page 2: Datamapper Railskonferenz 2009

SalesLentz::DevTeam

2

Page 3: Datamapper Railskonferenz 2009

# 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

Über uns

3

Page 4: Datamapper Railskonferenz 2009

Wer ist ein Rails Newbie ?

4

Page 5: Datamapper Railskonferenz 2009

Dan Kubb – Ruby Hero

5

Page 6: Datamapper Railskonferenz 2009

Wer setzt DataMapper ein ?

6

Page 7: Datamapper Railskonferenz 2009

Intro

7

Page 8: Datamapper Railskonferenz 2009

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::Baseend

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

puts Shoe.first.brand# => Geox

8

Page 9: Datamapper Railskonferenz 2009

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, Booleanend

Shoe.auto_migrate!

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

puts Shoe.first.brand# => Geox

9

Page 10: Datamapper Railskonferenz 2009

Migrations

10

Page 11: Datamapper Railskonferenz 2009

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 endend

rake db:migrate

11

Page 12: Datamapper Railskonferenz 2009

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 endend

rake db:migrate

12

Page 13: Datamapper Railskonferenz 2009

DataMapper Migrations

# Neue Tabelle erstellen

class Shoe include DataMapper::Resource property :id, Serial property :brand, String property :price, Floatend

# Tabelle shoes erstellen# Vorsicht: Daten gehen verlorenShoe.auto_migrate!

# alle Tabellen erstellen# Vorsicht: Daten gehen verlorenDataMapper.auto_migrate!

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

13

Page 14: Datamapper Railskonferenz 2009

DataMapper Migrations

# Neues Feld hinzufügen

class Shoe include DataMapper::Resource property :id, Serial property :brand, String property :price, Float property :available, Booleanend

# Vorsicht: Daten gehen verlorenShoe.auto_migrate!

14

Page 15: Datamapper Railskonferenz 2009

Extended Types

15

Page 16: Datamapper Railskonferenz 2009

DataMapper Extended Types

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

shoe = Shoe.newshoe.color = :redshoe.image_path = "/images/shoes.jpg"shoe.image_path.class# => Pathnameshoe.image_path.basename# => shoes.jpg

16

Page 17: Datamapper Railskonferenz 2009

ActiveRecord

?Extended Types

17

Page 18: Datamapper Railskonferenz 2009

Defaults

18

Page 19: Datamapper Railskonferenz 2009

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 endend

rake db:migrate

19

Page 20: Datamapper Railskonferenz 2009

DataMapper Defaults

# Dynamische Default-Werte

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

property :tax, Float, :default => 19.0end

DataMapper.auto_migrate!

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

20

Page 21: Datamapper Railskonferenz 2009

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

Page 22: Datamapper Railskonferenz 2009

ActiveRecord

?Dynamic Defaults

22

Page 23: Datamapper Railskonferenz 2009

Validations

23

Page 24: Datamapper Railskonferenz 2009

ActiveRecord Validations

# Model ohne Validierung

class Woman < ActiveRecord::Baseend

24

Page 25: Datamapper Railskonferenz 2009

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 :emailend

25

Page 26: Datamapper Railskonferenz 2009

DataMapper Validations

# Model ohne Validierung

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

end

26

Page 27: Datamapper Railskonferenz 2009

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

Page 28: Datamapper Railskonferenz 2009

Identity Map

28

Page 29: Datamapper Railskonferenz 2009

ActiveRecord Identity Map

Shoe.first.eql? Shoe.first

# => false

29

Page 30: Datamapper Railskonferenz 2009

DataMapper Identity Map

Shoe.first.eql? Shoe.first

# => true

30

Page 31: Datamapper Railskonferenz 2009

Lazy Loading

31

Page 32: Datamapper Railskonferenz 2009

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 => trueend

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

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

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

32

Page 33: Datamapper Railskonferenz 2009

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=1my_shoe = Shoe.get(1)

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

# Keine Datenbankabfragemy_shoe.description

33

Page 34: Datamapper Railskonferenz 2009

ActiveRecord

?Lazy Loading

34

Page 35: Datamapper Railskonferenz 2009

ActiveRecord Lazy Loading

class Shoe < ActiveRecord::Baseend

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

my_shoe.description # => Exception

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

35

Page 36: Datamapper Railskonferenz 2009

Keys

36

Page 37: Datamapper Railskonferenz 2009

ActiveRecord Keys

# Primary Keys automatisch in Migration# Immer Integer

37

Page 38: Datamapper Railskonferenz 2009

DataMapper Keys

class Woman include DataMapper::Resource property :id, Integer, :serial => true # ...end

Woman.get(7)

38

Page 39: Datamapper Railskonferenz 2009

DataMapper Keys

# Kurzform

class Woman include DataMapper::Resource property :id, Serial # ...end

Woman.get(7)

39

Page 40: Datamapper Railskonferenz 2009

DataMapper Keys

# Natürlicher Key

class Woman include DataMapper::Resource property :steuer_identifikationsnummer, :key => trueend

Woman.get("i2930d980324")

40

Page 41: Datamapper Railskonferenz 2009

DataMapper Keys

# Composite Keys

class Woman include DataMapper::Resource property :steuer_identifikationsnummer, :key => true property :pass_nr, :key => trueend

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

41

Page 42: Datamapper Railskonferenz 2009

Search

42

Page 43: Datamapper Railskonferenz 2009

ActiveRecord Search

class Shoe < ActiveRecord::Baseend

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

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

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

# brand IS NOT NULLShoe.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

Page 44: Datamapper Railskonferenz 2009

DataMapper Search

class Shoe include DataMapper::Resource property :id, Serial property :brand, String property :price, Floatend

DataMapper.auto_migrate!

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

44

Page 45: Datamapper Railskonferenz 2009

DataMapper Search

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

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

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

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

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

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

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

45

Page 46: Datamapper Railskonferenz 2009

Named Scope

46

Page 47: Datamapper Railskonferenz 2009

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

Page 48: Datamapper Railskonferenz 2009

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) endend

Shoe.available.cheaper(210.0)

48

Page 49: Datamapper Railskonferenz 2009

Associations

49

Page 50: Datamapper Railskonferenz 2009

ActiveRecord Associations

class Woman has_many :shoesend

class Shoe belongs_to :woman has_many :categories, :through => :categorisationsend

50

Page 51: Datamapper Railskonferenz 2009

DataMapper Associations

class Woman include DataMapper::Resource property :id, Serial property :name, String has n, :shoesend

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 => :categorisationsend

51

Page 52: Datamapper Railskonferenz 2009

Timestamps

52

Page 53: Datamapper Railskonferenz 2009

ActiveRecord Timestamps

# Neue Tabelle erstellen mit einer Migrationclass 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 endend

# Modelclass Shoe < ActiveRecord::Baseend

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

53

Page 54: Datamapper Railskonferenz 2009

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, DateTimeend

DataMapper.auto_migrate!

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

54

Page 55: Datamapper Railskonferenz 2009

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, DateTimeend

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

Page 56: Datamapper Railskonferenz 2009

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_atend

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

Page 57: Datamapper Railskonferenz 2009

DataMapper Timestamps

require 'initdb'require 'dm-timestamps'

class Shoe include DataMapper::Resource property :id, Serial property :title, String property :price, Float timestamps :atend

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

Page 58: Datamapper Railskonferenz 2009

Multi Databases

58

Page 59: Datamapper Railskonferenz 2009

ActiveRecord

?Multi Databases

59

Page 60: Datamapper Railskonferenz 2009

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, Stringend

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

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

60

Page 61: Datamapper Railskonferenz 2009

Naming Conventions

61

Page 62: Datamapper Railskonferenz 2009

ActiveRecord Naming Conventions

class Shoe < ActiveRecord::Base set_table_name "tbl_Shoe"end

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

62

Page 63: Datamapper Railskonferenz 2009

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

Page 64: Datamapper Railskonferenz 2009

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

Page 65: Datamapper Railskonferenz 2009

Legacy Databases

65

Page 66: Datamapper Railskonferenz 2009

ActiveRecord

?Legacy Databases

66

Page 67: Datamapper Railskonferenz 2009

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 => trueend

# Im Gegensatz zu ActiveRecord werden nur die angegebenen Felder gelesen

67

Page 68: Datamapper Railskonferenz 2009

Adapter

68

Page 69: Datamapper Railskonferenz 2009

ActiveRecord Adapter

MySQL

PostgreSQL

SQLite

Oracle

69

Page 70: Datamapper Railskonferenz 2009

DataMapper Adapter

MySQL

PostgreSQL

SQLite

Oracle

IMAPYAML ...

70

Page 71: Datamapper Railskonferenz 2009

Rails 3

71

Page 72: Datamapper Railskonferenz 2009

Fazit

72

Page 73: Datamapper Railskonferenz 2009

one more thing...

73

Page 74: Datamapper Railskonferenz 2009

74

Page 75: Datamapper Railskonferenz 2009

Solo Division Winner: Jacques Crocker

75

Page 76: Datamapper Railskonferenz 2009

mit DataMapper gemacht!

76

Page 77: Datamapper Railskonferenz 2009

http://github.com/merbjedi/alertme_tv

77

Page 78: Datamapper Railskonferenz 2009

78