datamapper
the persistence framework
who am I?
(Booth 501)
DataMapper
datamapper
object relational
     mapper
like activerecord
like activerecord
★ DB adapters     ★ many-to-many

★ migrations      ★ -through

★ associations    ★ polymorphic

 ★ one-...
drops into Rails
       1.0
(or merb)
   0.9
architecture
Application    Merb        Rails

                 DataMapper

  Adapters    DO.rb YAML   IMAP

Data Stores
some caveats
work in progress
    0.9   1.0
be prepared for code
why did we build it?
identity map
Foo[1]   Foo

         id = 1



Foo[1]     ...
foo[1] == foo[1]
     #=> true
loadedset
foo.all

Foo      Foo      Foo       Foo     Foo      Foo
id = 1   id = 2   id = 3   id = 4   id = 5   id = 6

  ...      ...
composite keys
belongs_to :project,
  :child_key => [:name, :tag]
legacy data
naming conventions
       (yours)
naming conventions
          underscored
   foo::barBaz => foo/bar_baz
naming conventions
   underscoredandpluralized
   foo::barBaz => foo_bar_bazs
naming conventions
underscoredandpluralizedwithoutmodule
          foo::barBaz => bazs
naming conventions
               yaml
    foo::Bar => foo/bars.yaml
support for multiple
     databases
     (even in the same model)
Post.all(:repository => :legacy)
Post.all
  # :repository => :default
prepared statements
        1.0
custom types
embedded values
      1.0
Employments          Employment

      id: int         id<Integer>
  person_id: int
                    person<Person>
   ...
declared properties
    property :id, :key => true
robust queries
Child.all(
  “mother.last_name.like” =>
    “Jane%”,
  :name.like => “Jim”
)
dirty tracking
modularity
unified interface for
      drivers
•connections
• commands
• readers
• cursors (forward-only)
• quoting
• transactions
Connection     Connection      Connection     Connection      Connection

                              Connection Pool


...
works today on:
mysql, sqlite, postgres
fast, written in C
simple interface for
     adapters
•read by key
• read by query
• update by key
• update set
• delete
• (optional: transactions)
salesforce adapter in
       200 LOC
Errors

Operators

Naming
Conventions

~/.salesforce

Build Query

Load Result Set

Similar CRUD

Demo
what does it look like?
Zoo.all(
  :age.gt => 30,
  :name.not =>
    [“bob”, “jones”]
)
SELECT
  “age”, “name”, “description”
FROM “zoos”
WHERE
  (“age” > 30) AND
  (“name” NOT IN
    (“bob”, “jones”))
Zoo.first.eql? Zoo.first
          #=> true
Zoo.all.map {|x| x.animals }
        how many queries?
                2
we call this
strategic eager loading.
lazy loading
class Post
  include DataMapper::Resource
  property :id, Fixnum,
    :serial => true
  property :title, String
  property...
posts = Post.all
SELECT “id”, “title”
FROM “posts”
return two objects
    ids 1 and 2
posts.first.body
SELECT “body”
FROM “posts”
WHERE (“id” IN (1,2))
posts.map{|x| x.body}
SELECT “body”
FROM “posts”
WHERE (“id” IN (1,2))
lazy loaded grouping
class Post
  include DataMapper::Resource
  property :id, Fixnum,
    :serial => true
  property :title, String,
    :lazy...
you can go off the
   golden path
class Post
  include DataMapper::Resource
  property :title, String

  repository(:legacy) do
    property :title, String,...
Post.all(:repository => :legacy)

repository(:legacy) do
  Post.all
end
Post.all

Post.all(:repository =>
  :default)

repository(:default) do
  Post.all
end
naming conventions
repository(:legacy).adapter.
  resource_naming_convention =
    DM::
    NamingConventions::
    Unders...
naming conventions
repository(:legacy).adapter.
  resource_naming_convention =
    lambda do |klass|
      “tbl#{klass.cam...
default repository
class Post
  include DataMapper::Resource
  def self.default_repository_name
    :legacy
  end
end
import data
Post.copy(:legacy, :default)

Post.copy(:legacy, :default,
  :created_at.gt =>
    Date.today - 365)
         ...
import data
class Post
  property :title, String

  repository(:legacy) do
    property :title, String,
      :field => “T...
custom types
primitives
 Trueclass, string, text, float, fixnum,
bigdecimal, datetime, date, object, class
custom types
class Post
  include DataMapper::Resource
  property :title, String
  property :author, FullName
  property :...
class FullName < DM::Type
  primitive String
  size 100

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

  def sel...
class Csv < DM::Type
  primitive String
  size 65355

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

  def self.du...
Post.create!(
  :title => “New Post”,
  :author => [“Yehuda”, “Katz”],
  :metadata => [
    [“Some”, “Sample”, “Data”],
  ...
in the database
  Title        “New Post”



Author       “Katz, Yehuda”


           “Some,Sample,Datan
Metadata
        ...
and it’s lazy-parsed
custom stores
stores are uris
mysql://user@localhost
setting up
DataMapper.setup(
  :default,
  “mysql://user@localhost”
)
database.yml
development:
  default:
    adapter: mysql
    database: app_dev
    user: person
    password: sekrit
database.yml
legacy:
  adapter: sqlite3
  database: config/l3g.db
yaml:///fixtures


                  1.0
ssh+yaml://
fixtures.engineyard.com/
       fixtures
                          1+
database.yml
test:
  default:
    adapter: yaml
    database: app_test.db
  legacy:
    adapter: yaml
    database: l3g_te...
making fixtures
Post.copy(:default, :fixtures)

rake db:copy_fixtures
validations
class Product
  include DataMapper::Resource
  property :title, String
  property :price, String,
            validates_le...
class Product
  include DataMapper::Resource
  property :title, String
  property :number, String,
    :format =>
      /d...
class Product
  include DataMapper::Resource
  property :title, String
  property :number, String,
    :format => proc {|n...
class Product
  include DataMapper::Resource
  property :title, String
  property :number, String,
    :length => 2..10,
 ...
class Product
  include DataMapper::Resource
  property :title, String
  property :number, String,
  validates_length_of :...
thank you.
any questions?
</railsconf>
DataMapper
Upcoming SlideShare
Loading in...5
×

DataMapper

21,278

Published on

Learn all about the state of DataMapper.

Published in: Technology, Business
3 Comments
36 Likes
Statistics
Notes
No Downloads
Views
Total Views
21,278
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
374
Comments
3
Likes
36
Embeds 0
No embeds

No notes for slide

DataMapper

  1. 1. datamapper the persistence framework
  2. 2. who am I?
  3. 3. (Booth 501)
  4. 4. DataMapper
  5. 5. datamapper
  6. 6. object relational mapper
  7. 7. like activerecord
  8. 8. like activerecord ★ DB adapters ★ many-to-many ★ migrations ★ -through ★ associations ★ polymorphic ★ one-to-one ★ lifecycle events ★ one-to-many ★ sti ★ many-to-one ★ etc.
  9. 9. drops into Rails 1.0
  10. 10. (or merb) 0.9
  11. 11. architecture Application Merb Rails DataMapper Adapters DO.rb YAML IMAP Data Stores
  12. 12. some caveats
  13. 13. work in progress 0.9 1.0
  14. 14. be prepared for code
  15. 15. why did we build it?
  16. 16. identity map
  17. 17. Foo[1] Foo id = 1 Foo[1] ...
  18. 18. foo[1] == foo[1] #=> true
  19. 19. loadedset
  20. 20. foo.all Foo Foo Foo Foo Foo Foo id = 1 id = 2 id = 3 id = 4 id = 5 id = 6 ... ... ... ... ... ... LoadedSet
  21. 21. composite keys
  22. 22. belongs_to :project, :child_key => [:name, :tag]
  23. 23. legacy data
  24. 24. naming conventions (yours)
  25. 25. naming conventions underscored foo::barBaz => foo/bar_baz
  26. 26. naming conventions underscoredandpluralized foo::barBaz => foo_bar_bazs
  27. 27. naming conventions underscoredandpluralizedwithoutmodule foo::barBaz => bazs
  28. 28. naming conventions yaml foo::Bar => foo/bars.yaml
  29. 29. support for multiple databases (even in the same model)
  30. 30. Post.all(:repository => :legacy) Post.all # :repository => :default
  31. 31. prepared statements 1.0
  32. 32. custom types
  33. 33. embedded values 1.0
  34. 34. Employments Employment id: int id<Integer> person_id: int person<Person> start: date end: date start<Date> salary_amt: dec end<Date> salary_cur: char salary<Money>
  35. 35. declared properties property :id, :key => true
  36. 36. robust queries
  37. 37. Child.all( “mother.last_name.like” => “Jane%”, :name.like => “Jim” )
  38. 38. dirty tracking
  39. 39. modularity
  40. 40. unified interface for drivers
  41. 41. •connections • commands • readers • cursors (forward-only) • quoting • transactions
  42. 42. Connection Connection Connection Connection Connection Connection Pool create_command “select * from foos where id = ?” Command execute_reader Reader next values next ... execute_reader(12) => select * from foos where id = 12
  43. 43. works today on: mysql, sqlite, postgres
  44. 44. fast, written in C
  45. 45. simple interface for adapters
  46. 46. •read by key • read by query • update by key • update set • delete • (optional: transactions)
  47. 47. salesforce adapter in 200 LOC
  48. 48. Errors Operators Naming Conventions ~/.salesforce Build Query Load Result Set Similar CRUD Demo
  49. 49. what does it look like?
  50. 50. Zoo.all( :age.gt => 30, :name.not => [“bob”, “jones”] )
  51. 51. SELECT “age”, “name”, “description” FROM “zoos” WHERE (“age” > 30) AND (“name” NOT IN (“bob”, “jones”))
  52. 52. Zoo.first.eql? Zoo.first #=> true
  53. 53. Zoo.all.map {|x| x.animals } how many queries? 2
  54. 54. we call this strategic eager loading.
  55. 55. lazy loading
  56. 56. class Post include DataMapper::Resource property :id, Fixnum, :serial => true property :title, String property :body, Text, :lazy => true end
  57. 57. posts = Post.all SELECT “id”, “title” FROM “posts”
  58. 58. return two objects ids 1 and 2
  59. 59. posts.first.body SELECT “body” FROM “posts” WHERE (“id” IN (1,2))
  60. 60. posts.map{|x| x.body} SELECT “body” FROM “posts” WHERE (“id” IN (1,2))
  61. 61. lazy loaded grouping
  62. 62. class Post include DataMapper::Resource property :id, Fixnum, :serial => true property :title, String, :lazy => [:details] property :body, Text, :lazy => [:details] end
  63. 63. you can go off the golden path
  64. 64. class Post include DataMapper::Resource property :title, String repository(:legacy) do property :title, String, :field => “T1tLz” end end
  65. 65. Post.all(:repository => :legacy) repository(:legacy) do Post.all end
  66. 66. Post.all Post.all(:repository => :default) repository(:default) do Post.all end
  67. 67. naming conventions repository(:legacy).adapter. resource_naming_convention = DM:: NamingConventions:: Underscored AndPluralized
  68. 68. naming conventions repository(:legacy).adapter. resource_naming_convention = lambda do |klass| “tbl#{klass.camel_case}” end
  69. 69. default repository class Post include DataMapper::Resource def self.default_repository_name :legacy end end
  70. 70. import data Post.copy(:legacy, :default) Post.copy(:legacy, :default, :created_at.gt => Date.today - 365) 1.0
  71. 71. import data class Post property :title, String repository(:legacy) do property :title, String, :field => “TIT13” end end
  72. 72. custom types
  73. 73. primitives Trueclass, string, text, float, fixnum, bigdecimal, datetime, date, object, class
  74. 74. custom types class Post include DataMapper::Resource property :title, String property :author, FullName property :details, Csv end
  75. 75. class FullName < DM::Type primitive String size 100 def self.load(str) str.split(“, ”).reverse end def self.dump(ary) ary.reverse.join(“, ”) end end
  76. 76. 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 end end
  77. 77. Post.create!( :title => “New Post”, :author => [“Yehuda”, “Katz”], :metadata => [ [“Some”, “Sample”, “Data”], [“More”, “Sample”, “Data”] ] )
  78. 78. in the database Title “New Post” Author “Katz, Yehuda” “Some,Sample,Datan Metadata More,Sample,Datan”
  79. 79. and it’s lazy-parsed
  80. 80. custom stores
  81. 81. stores are uris
  82. 82. mysql://user@localhost
  83. 83. setting up DataMapper.setup( :default, “mysql://user@localhost” )
  84. 84. database.yml development: default: adapter: mysql database: app_dev user: person password: sekrit
  85. 85. database.yml legacy: adapter: sqlite3 database: config/l3g.db
  86. 86. yaml:///fixtures 1.0
  87. 87. ssh+yaml:// fixtures.engineyard.com/ fixtures 1+
  88. 88. database.yml test: default: adapter: yaml database: app_test.db legacy: adapter: yaml database: l3g_test.db
  89. 89. making fixtures Post.copy(:default, :fixtures) rake db:copy_fixtures
  90. 90. validations
  91. 91. class Product include DataMapper::Resource property :title, String property :price, String, validates_length_of :nullable => false, :validation_context => validates_presence_of :purchase end valid_for_purchase?
  92. 92. class Product include DataMapper::Resource property :title, String property :number, String, :format => /d{3}-[a-zA-Z]{9}-0/ end validates_format_of
  93. 93. class Product include DataMapper::Resource property :title, String property :number, String, :format => proc {|n| n.split(“-”).size == 2} validates_format_of end
  94. 94. class Product include DataMapper::Resource property :title, String property :number, String, :length => 2..10, :validation_context => validates_length_of :import valid_for_import? save(:import) end
  95. 95. class Product include DataMapper::Resource property :title, String property :number, String, validates_length_of :number, :in => (2..10), :when => :import end valid_for_import?
  96. 96. thank you.
  97. 97. any questions?
  98. 98. </railsconf>
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×