MongoMapper
Mapping Ruby To and From Mongo




MongoSF San Francisco, CA   John Nunemaker
April 30, 2010                  ...
Using
Extending
Prophesying
Using
Extending
Prophesying
...and many more.
class Item
end
class Item
  include MongoMapper::Document
end
class Datum
  include MongoMapper::EmbeddedDocument
end
Free Stuff
Free Stuff
 Persistence
Free Stuff
 Persistence
 Validations   [presence, length, inclusion, ...]
Free Stuff
 Persistence
 Validations   [presence, length, inclusion, ...]


 Callbacks     [before/after validate, create, ...
Free Stuff
 Persistence
 Validations    [presence, length, inclusion, ...]


 Callbacks      [before/after validate, create...
Free Stuff
 Persistence
 Validations     [presence, length, inclusion, ...]


 Callbacks       [before/after validate, crea...
Persistence
Never gonna give you up
item = Item.create({
   :title    => 'MongoSF',
   :location => 'San Fran',
   :when     => Time.now
})
puts item.to_mongo

{
    "_id"        =>   ObjectID('4bd8cc5cbcd1b313b3000001'),
    "title"      =>   "MongoSF",
    "lo...
item              =   Item.new
item[:title]      =   'MongoSF'
item[:location]   =   'San Fran'
item[:when]       =   Time...
puts item.to_mongo

{
    "_id"        =>   ObjectID('4bd8cc5cbcd1b313b3000001'),
    "title"      =>   "MongoSF",
    "lo...
Types
What you be baby boo?
class Item
  include MongoMapper::Document

  key :title, String
  key :path, String
end
But Mongo is Schema-less?
Instead of database schema

Think App Schema
Built-in Types
Array, Binary, Boolean, Date, Float, Hash,
Integer, Nil, ObjectId, Set, String, Time
Custom Types
Its shake and bake and I helped!
class Set
  def self.to_mongo(value)
    value.to_a
  end

  def self.from_mongo(value)
    Set.new(value || [])
  end
end
class DowncasedString
  def self.to_mongo(value)
    value.nil? ? nil : value.to_s.downcase
  end

  def self.from_mongo(v...
class User
  include MongoMapper::Document

  key :email, DowncasedString
end
Typeless
I do not know who I am
class Foo
  include MongoMapper::Document
  key :bar
end

foo = Foo.new

foo.bar = 'Some text'
# foo.bar => "Some text"

f...
Validations
Currently using fork of validatable
class Item
  include MongoMapper::Document

  key :title, String
  validates_presence_of :title
end
class Item
  include MongoMapper::Document

  key :title, String, :required => true
end
validates_presence_of
validates_length_of
validates_format_of
validates_numericality_of
validates_acceptance_of
validates_...
Callbacks
Ripped from AS2’s cold, dead fingers
class Item
  include MongoMapper::Document

  key :title, String
  key :path, String
  key :parent_id, ObjectId
  belongs_...
:before_save,                   :after_save,
:before_create,                 :after_create,
:before_update,               ...
Associations
I belong to you
to Docs
belongs_to, one, many, many :in
class Account
  include MongoMapper::Document

  many :sites
end

class Site
  include MongoMapper::Document

  key :accou...
account = Account.create(:title => 'OL', :sites => [
   Site.new(:title => 'OL', :domain => 'orderedlist.com'),
   Site.ne...
[
    {
         '_id'          =>   ObjectID('...'),
         'title'        =>   'OL',
         'domain'       =>   'ord...
to Embedded Docs
many, one
class Item
  include MongoMapper::Document

  many :data
end

class Datum
  include MongoMapper::EmbeddedDocument

  key :...
Item.create(:title => 'MongoSF', :data => [
   Datum.new(:key => 'description', :value => 'Awesome.')
])
{
    '_id'   => ObjectID('...'),
    'title' => 'MongoSF',
    'data' => [
      {
        '_id'   => ObjectID('...'),
  ...
Using
Extending
Prophesying
Plugins
Conventional way to extend
MongoMapper is

Powered by Plugins
associations, callbacks, clone, descendants,
dirty, equality, identity_map, inspect, ke...
module MongoMapper
  module Plugins
    def plugins
      @plugins ||= []
    end

    def plugin(mod)
      extend mod::C...
module ActsAsListFu
  module ClassMethods
    def reorder(ids)
      # reorder ids...
    end
  end

  module InstanceMeth...
class Foo
  include MongoMapper::Document
  plugin ActsAsListFu
end

Foo.reorder(...)
Foo.new.move_to_top
Good Example
Joint: github.com/jnunemaker/joint
class Asset
  include MongoMapper::Document
  plugin Joint

  attachment :image
  attachment :file
end
asset = Asset.create({
   :image => File.open('john.jpg', 'r'),
   :file  => File.open('foo.txt', 'r'),
})

asset.image.id...
Descendant Appends
Fancy Schmancy and Stolen
module FancySchmancy
  def some_method
    puts 'some method'
  end
end

MongoMapper::Document.append_extensions(FancySchm...
module FancySchmancy
  def some_method
    puts 'some method'
  end
end

MongoMapper::Document.append_inclusions(FancySchm...
module FancySchmancy
  def some_method
    puts 'some method'
  end
end

class Foo
  include MongoMapper::Document
end

Mo...
module IdentityMapAddition
  def self.included(model)
    model.plugin MongoMapper::Plugins::IdentityMap
  end
end

MongoM...
Using
Extending
Prophesying
Active Model
Validations, callbacks, serialization, etc.
Blank Document
Mix and match whatever you want
Mongo::Query
Fancy query magic for the ruby driver
github.com/jnunemaker/mongo-query
ideafoundry.info/mongodb
mongotips.com
railstips.org
Thank you!
john@orderedlist.com
@jnunemaker



MongoSF San Francisco, CA   John Nunemaker
April 30, 2010                  ...
MongoMapper - Mapping Ruby to and from Mongo
MongoMapper - Mapping Ruby to and from Mongo
Upcoming SlideShare
Loading in...5
×

MongoMapper - Mapping Ruby to and from Mongo

10,021

Published on

1 Comment
19 Likes
Statistics
Notes
No Downloads
Views
Total Views
10,021
On Slideshare
0
From Embeds
0
Number of Embeds
15
Actions
Shares
0
Downloads
165
Comments
1
Likes
19
Embeds 0
No embeds

No notes for slide

MongoMapper - Mapping Ruby to and from Mongo

  1. 1. MongoMapper Mapping Ruby To and From Mongo MongoSF San Francisco, CA John Nunemaker April 30, 2010 Ordered List
  2. 2. Using Extending Prophesying
  3. 3. Using Extending Prophesying
  4. 4. ...and many more.
  5. 5. class Item end
  6. 6. class Item include MongoMapper::Document end
  7. 7. class Datum include MongoMapper::EmbeddedDocument end
  8. 8. Free Stuff
  9. 9. Free Stuff Persistence
  10. 10. Free Stuff Persistence Validations [presence, length, inclusion, ...]
  11. 11. Free Stuff Persistence Validations [presence, length, inclusion, ...] Callbacks [before/after validate, create, save, ...]
  12. 12. Free Stuff Persistence Validations [presence, length, inclusion, ...] Callbacks [before/after validate, create, save, ...] Associations [many, belongs_to, one, ...]
  13. 13. Free Stuff Persistence Validations [presence, length, inclusion, ...] Callbacks [before/after validate, create, save, ...] Associations [many, belongs_to, one, ...] Serialization [to_json]
  14. 14. Persistence Never gonna give you up
  15. 15. item = Item.create({ :title => 'MongoSF', :location => 'San Fran', :when => Time.now })
  16. 16. puts item.to_mongo { "_id" => ObjectID('4bd8cc5cbcd1b313b3000001'), "title" => "MongoSF", "location" => "San Fran", "when" => Wed Apr 28 17:01:32 -0700 2010 }
  17. 17. item = Item.new item[:title] = 'MongoSF' item[:location] = 'San Fran' item[:when] = Time.now item.save
  18. 18. puts item.to_mongo { "_id" => ObjectID('4bd8cc5cbcd1b313b3000001'), "title" => "MongoSF", "location" => "San Fran", "when" => Wed Apr 28 17:01:32 -0700 2010 }
  19. 19. Types What you be baby boo?
  20. 20. class Item include MongoMapper::Document key :title, String key :path, String end
  21. 21. But Mongo is Schema-less?
  22. 22. Instead of database schema Think App Schema
  23. 23. Built-in Types Array, Binary, Boolean, Date, Float, Hash, Integer, Nil, ObjectId, Set, String, Time
  24. 24. Custom Types Its shake and bake and I helped!
  25. 25. class Set def self.to_mongo(value) value.to_a end def self.from_mongo(value) Set.new(value || []) end end
  26. 26. class DowncasedString def self.to_mongo(value) value.nil? ? nil : value.to_s.downcase end def self.from_mongo(value) value.nil? ? nil : value.to_s.downcase end end
  27. 27. class User include MongoMapper::Document key :email, DowncasedString end
  28. 28. Typeless I do not know who I am
  29. 29. class Foo include MongoMapper::Document key :bar end foo = Foo.new foo.bar = 'Some text' # foo.bar => "Some text" foo.bar = 24 # foo.bar => 24
  30. 30. Validations Currently using fork of validatable
  31. 31. class Item include MongoMapper::Document key :title, String validates_presence_of :title end
  32. 32. class Item include MongoMapper::Document key :title, String, :required => true end
  33. 33. validates_presence_of validates_length_of validates_format_of validates_numericality_of validates_acceptance_of validates_confirmation_of validates_inclusion_of validates_exclusion_of
  34. 34. Callbacks Ripped from AS2’s cold, dead fingers
  35. 35. class Item include MongoMapper::Document key :title, String key :path, String key :parent_id, ObjectId belongs_to :parent before_validation :set_path private def set_path self.path = parent.path + title.parameterize end end
  36. 36. :before_save, :after_save, :before_create, :after_create, :before_update, :after_update, :before_validation, :after_validation, :before_validation_on_create, :after_validation_on_create, :before_validation_on_update, :after_validation_on_update, :before_destroy, :after_destroy, :validate_on_create, :validate_on_update, :validate
  37. 37. Associations I belong to you
  38. 38. to Docs belongs_to, one, many, many :in
  39. 39. class Account include MongoMapper::Document many :sites end class Site include MongoMapper::Document key :account_id, ObjectId belongs_to :account end
  40. 40. account = Account.create(:title => 'OL', :sites => [ Site.new(:title => 'OL', :domain => 'orderedlist.com'), Site.new(:title => 'RT', :domain => 'railstips.org'), ])
  41. 41. [ { '_id' => ObjectID('...'), 'title' => 'OL', 'domain' => 'orderedlist.com' 'account_id' => ObjectID('...'), }, { '_id' => ObjectID('...'), 'title' => 'RT', 'domain' => 'railstips.org' 'account_id' => ObjectID('...'), } ]
  42. 42. to Embedded Docs many, one
  43. 43. class Item include MongoMapper::Document many :data end class Datum include MongoMapper::EmbeddedDocument key :key, String key :value end
  44. 44. Item.create(:title => 'MongoSF', :data => [ Datum.new(:key => 'description', :value => 'Awesome.') ])
  45. 45. { '_id' => ObjectID('...'), 'title' => 'MongoSF', 'data' => [ { '_id' => ObjectID('...'), 'key' => 'description' 'value' => 'Awesome.', } ] }
  46. 46. Using Extending Prophesying
  47. 47. Plugins Conventional way to extend
  48. 48. MongoMapper is Powered by Plugins associations, callbacks, clone, descendants, dirty, equality, identity_map, inspect, keys, logger, modifiers, pagination, persistence, protected, rails, serialization, timestamps, userstamps, validations
  49. 49. module MongoMapper module Plugins def plugins @plugins ||= [] end def plugin(mod) extend mod::ClassMethods if mod.const_defined?(:ClassMethods) include mod::InstanceMethods if mod.const_defined?(:InstanceMethods) mod.configure(self) if mod.respond_to?(:configure) plugins << mod end end end
  50. 50. module ActsAsListFu module ClassMethods def reorder(ids) # reorder ids... end end module InstanceMethods def move_to_top # move to top end end def self.configure(model) model.key :position, Integer, :default => 1 end end
  51. 51. class Foo include MongoMapper::Document plugin ActsAsListFu end Foo.reorder(...) Foo.new.move_to_top
  52. 52. Good Example Joint: github.com/jnunemaker/joint
  53. 53. class Asset include MongoMapper::Document plugin Joint attachment :image attachment :file end
  54. 54. asset = Asset.create({ :image => File.open('john.jpg', 'r'), :file => File.open('foo.txt', 'r'), }) asset.image.id asset.image.name asset.image.type asset.image.size asset.image.read
  55. 55. Descendant Appends Fancy Schmancy and Stolen
  56. 56. module FancySchmancy def some_method puts 'some method' end end MongoMapper::Document.append_extensions(FancySchmancy) class Foo include MongoMapper::Document end Foo.some_method # puts 'some method' Foo.new.some_method # NoMethodError
  57. 57. module FancySchmancy def some_method puts 'some method' end end MongoMapper::Document.append_inclusions(FancySchmancy) class Foo include MongoMapper::Document end Foo.new.some_method # puts 'some method' Foo.some_method # NoMethodError
  58. 58. module FancySchmancy def some_method puts 'some method' end end class Foo include MongoMapper::Document end MongoMapper::Document.append_extensions(FancySchmancy) class Bar include MongoMapper::Document end Foo.some_method # puts 'some method' Bar.some_method # puts 'some method'
  59. 59. module IdentityMapAddition def self.included(model) model.plugin MongoMapper::Plugins::IdentityMap end end MongoMapper::Document.append_inclusions(IdentityMapAddition)
  60. 60. Using Extending Prophesying
  61. 61. Active Model Validations, callbacks, serialization, etc.
  62. 62. Blank Document Mix and match whatever you want
  63. 63. Mongo::Query Fancy query magic for the ruby driver github.com/jnunemaker/mongo-query
  64. 64. ideafoundry.info/mongodb
  65. 65. mongotips.com
  66. 66. railstips.org
  67. 67. Thank you! john@orderedlist.com @jnunemaker MongoSF San Francisco, CA John Nunemaker April 30, 2010 Ordered List
  1. A particular slide catching your eye?

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

×