DataMapper

99
datamapper the persistence framework

description

Learn all about the state of DataMapper.

Transcript of DataMapper

Page 1: DataMapper

datamapperthe persistence framework

Page 2: DataMapper

who am I?

Page 3: DataMapper

(Booth 501)

Page 4: DataMapper

DataMapper

Page 5: DataMapper

datamapper

Page 6: DataMapper

object relational mapper

Page 7: DataMapper

like activerecord

Page 8: DataMapper

like activerecord★ DB adapters★ migrations★ associations★ one-to-one★ one-to-many★ many-to-one

★ many-to-many★ -through★ polymorphic

★ lifecycle events★ sti★ etc.

Page 9: DataMapper

drops into Rails1.0

Page 10: DataMapper

(or merb)0.9

Page 11: DataMapper

DataMapper

Merb Rails

DO.rb YAML IMAP

Application

Adapters

Data Stores

architecture

Page 12: DataMapper

some caveats

Page 13: DataMapper

1.0

work in progress0.9

Page 14: DataMapper

be prepared for code

Page 15: DataMapper

why did we build it?

Page 16: DataMapper

identity map

Page 17: DataMapper
Page 18: DataMapper

Foo[1]

Foo[1]

Foo

id = 1

...

Page 19: DataMapper

foo[1] == foo[1]#=> true

Page 20: DataMapper

loadedset

Page 21: DataMapper

LoadedSet

foo.all

Foo

id = 1

...

Foo

id = 2

...

Foo

id = 3

...

Foo

id = 4

...

Foo

id = 5

...

Foo

id = 6

...

Page 22: DataMapper

composite keys

Page 23: DataMapper

belongs_to :project, :child_key => [:name, :tag]

Page 24: DataMapper

legacy data

Page 25: DataMapper

naming conventions(yours)

Page 26: DataMapper

naming conventionsunderscored

foo::barBaz => foo/bar_baz

Page 27: DataMapper

naming conventionsunderscoredandpluralizedfoo::barBaz => foo_bar_bazs

Page 28: DataMapper

naming conventionsunderscoredandpluralizedwithoutmodule

foo::barBaz => bazs

Page 29: DataMapper

naming conventionsyaml

foo::Bar => foo/bars.yaml

Page 30: DataMapper

support for multiple databases(even in the same model)

Page 31: DataMapper

Post.all(:repository => :legacy)

Post.all # :repository => :default

Page 32: DataMapper

prepared statements1.0

Page 33: DataMapper

custom types

Page 34: DataMapper

embedded values1.0

Page 35: DataMapper

Employment

id<Integer>

person<Person>

start<Date>

end<Date>

salary<Money>

salary_cur: char

salary_amt: dec

end: date

start: date

person_id: int

id: int

Employments

Page 36: DataMapper

declared propertiesproperty :id, :key => true

Page 37: DataMapper

robust queries

Page 38: DataMapper

Child.all( “mother.last_name.like” => “Jane%”, :name.like => “Jim”)

Page 39: DataMapper

dirty tracking

Page 40: DataMapper

modularity

Page 41: DataMapper

unified interface for drivers

Page 42: DataMapper

•connections

•commands

•readers

•cursors (forward-only)

•quoting

• transactions

Page 43: DataMapper

Connection Pool

Connection Connection Connection Connection Connection

“select * from foos where id = ?”

Command

create_command

execute_reader Reader next values next ...

execute_reader(12) => select * from foos where id = 12

Page 44: DataMapper

works today on:mysql, sqlite, postgres

Page 45: DataMapper

fast, written in C

Page 46: DataMapper

simple interface for adapters

Page 47: DataMapper

•read by key

•read by query

•update by key

•update set

•delete

• (optional: transactions)

Page 48: DataMapper

salesforce adapter in 200 LOC

Page 49: DataMapper

Errors

Operators

NamingConventions

~/.salesforce

Build Query

Load Result Set

Similar CRUD

Demo

Page 50: DataMapper

what does it look like?

Page 51: DataMapper

Zoo.all( :age.gt => 30, :name.not => [“bob”, “jones”])

Page 52: DataMapper

SELECT “age”, “name”, “description”FROM “zoos”WHERE (“age” > 30) AND (“name” NOT IN (“bob”, “jones”))

Page 53: DataMapper

Zoo.first.eql? Zoo.first#=> true

Page 54: DataMapper

Zoo.all.map {|x| x.animals }how many queries?

2

Page 55: DataMapper

we call thisstrategic eager loading.

Page 56: DataMapper

lazy loading

Page 57: DataMapper

include DataMapper::Resource

property :id, Fixnum, :serial => true property :title, String property :body, Text, :lazy => trueend

class Post

Page 58: DataMapper

posts = Post.all

SELECT “id”, “title”FROM “posts”

Page 59: DataMapper

return two objectsids 1 and 2

Page 60: DataMapper

SELECT “body”FROM “posts”WHERE (“id” IN (1,2))

posts.first.body

Page 61: DataMapper

SELECT “body”FROM “posts”WHERE (“id” IN (1,2))

posts.map{|x| x.body}

Page 62: DataMapper

lazy loaded grouping

Page 63: DataMapper

include DataMapper::Resource

property :id, Fixnum, :serial => true property :title, String, :lazy => [:details] property :body, Text, :lazy => [:details]end

class Post

Page 64: DataMapper

you can go off the golden path

Page 65: DataMapper

class Post include DataMapper::Resource property :title, String

repository(:legacy) do property :title, String, :field => “T1tLz” endend

Page 66: DataMapper

Post.all(:repository => :legacy)

repository(:legacy) do Post.allend

Page 67: DataMapper

Post.all

Post.all(:repository => :default)

repository(:default) do Post.allend

Page 68: DataMapper

repository(:legacy).adapter. resource_naming_convention = DM:: NamingConventions:: Underscored

naming conventions

AndPluralized

Page 69: DataMapper

repository(:legacy).adapter. resource_naming_convention = lambda do |klass| “tbl#{klass.camel_case}” end

naming conventions

Page 70: DataMapper

default repositoryclass Post include DataMapper::Resource def self.default_repository_name :legacy endend

Page 71: DataMapper

import data

Post.copy(:legacy, :default)

Post.copy(:legacy, :default, :created_at.gt => Date.today - 365)

1.0

Page 72: DataMapper

import dataclass Post property :title, String

repository(:legacy) do property :title, String, :field => “TIT13” endend

Page 73: DataMapper

custom types

Page 74: DataMapper

primitivesTrueclass, string, text, float, fixnum,

bigdecimal, datetime, date, object, class

Page 75: DataMapper

custom types

class Post include DataMapper::Resource property :title, String property :author, FullName property :details, Csvend

Page 76: DataMapper

class FullName < DM::Type primitive String size 100

def self.load(str) str.split(“, ”).reverse end

def self.dump(ary) ary.reverse.join(“, ”) endend

Page 77: DataMapper

class Csv < DM::Type primitive String size 65355

def self.load(str) FasterCSV.parse(value) end

def self.dump(ary) FasterCSV.generate do |csv| ary.each {|line| csv << line} end endend

Page 78: DataMapper

Post.create!( :title => “New Post”, :author => [“Yehuda”, “Katz”], :metadata => [ [“Some”, “Sample”, “Data”], [“More”, “Sample”, “Data”] ])

Page 79: DataMapper

Title

Author

Metadata

“New Post”

“Katz, Yehuda”

“Some,Sample,Data\nMore,Sample,Data\n”

in the database

Page 80: DataMapper

and it’s lazy-parsed

Page 81: DataMapper

custom stores

Page 82: DataMapper

stores are uris

Page 83: DataMapper

mysql://user@localhost

Page 84: DataMapper

setting up

DataMapper.setup( :default, “mysql://user@localhost”)

Page 85: DataMapper

database.yml

development: default: adapter: mysql database: app_dev user: person password: sekrit

Page 86: DataMapper

database.yml

legacy: adapter: sqlite3 database: config/l3g.db

Page 87: DataMapper

yaml:///fixtures

1.0

Page 88: DataMapper

ssh+yaml://fixtures.engineyard.com/

fixtures

1+

Page 89: DataMapper

database.ymltest: default: adapter: yaml database: app_test.db legacy: adapter: yaml database: l3g_test.db

Page 90: DataMapper

making fixtures

Post.copy(:default, :fixtures)

rake db:copy_fixtures

Page 91: DataMapper

validations

Page 92: DataMapper

class Product include DataMapper::Resource property :title, String property :price, String, :nullable => false, :validation_context => :purchaseend

validates_length_of

validates_presence_of

valid_for_purchase?

Page 93: DataMapper

class Product include DataMapper::Resource property :title, String property :number, String, :format => /\d{3}-[a-zA-Z]{9}-0/end validates_format_of

Page 94: DataMapper

class Product include DataMapper::Resource property :title, String property :number, String, :format => proc {|n| n.split(“-”).size == 2}

end

validates_format_of

Page 95: DataMapper

class Product include DataMapper::Resource property :title, String property :number, String, :length => 2..10, :validation_context => :import

end

validates_length_of

valid_for_import?save(:import)

Page 96: DataMapper

class Product include DataMapper::Resource property :title, String property :number, String,

end valid_for_import?

validates_length_of :number, :in => (2..10), :when => :import

Page 97: DataMapper

thank you.

Page 98: DataMapper

any questions?

Page 99: DataMapper

</railsconf>