MongoMapper - Mapping Ruby to and from Mongo

Post on 08-May-2015

9.974 views 1 download

Transcript of MongoMapper - Mapping Ruby to and from Mongo

Ordered ListJohn NunemakerMongoSF San Francisco, CA

April 30, 2010

MongoMapperMapping Ruby To and From Mongo

UsingExtendingProphesying

UsingExtendingProphesying

...and many more.

class Itemend

class Item include MongoMapper::Documentend

class Datum include MongoMapper::EmbeddedDocumentend

Free Stuff

Free StuffPersistence

Free StuffPersistence

Validations [presence, length, inclusion, ...]

Free StuffPersistence

Validations [presence, length, inclusion, ...]

Callbacks [before/after validate, create, save, ...]

Free StuffPersistence

Validations [presence, length, inclusion, ...]

Callbacks [before/after validate, create, save, ...]

Associations [many, belongs_to, one, ...]

Free StuffPersistence

Validations [presence, length, inclusion, ...]

Callbacks [before/after validate, create, save, ...]

Associations [many, belongs_to, one, ...]

Serialization [to_json]

PersistenceNever gonna give you up

item = Item.create({ :title => 'MongoSF', :location => 'San Fran', :when => Time.now})

puts item.to_mongo

{ "_id" => ObjectID('4bd8cc5cbcd1b313b3000001'), "title" => "MongoSF", "location" => "San Fran", "when" => Wed Apr 28 17:01:32 -0700 2010}

item = Item.newitem[:title] = 'MongoSF'item[:location] = 'San Fran'item[:when] = Time.nowitem.save

puts item.to_mongo

{ "_id" => ObjectID('4bd8cc5cbcd1b313b3000001'), "title" => "MongoSF", "location" => "San Fran", "when" => Wed Apr 28 17:01:32 -0700 2010}

TypesWhat you be baby boo?

class Item include MongoMapper::Document key :title, String key :path, Stringend

But Mongo is Schema-less?

Think App SchemaInstead of database schema

Built-in TypesArray, Binary, Boolean, Date, Float, Hash, Integer, Nil, ObjectId, Set, String, Time

Custom TypesIts 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 || []) endend

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 endend

class User include MongoMapper::Document key :email, DowncasedStringend

TypelessI do not know who I am

class Foo include MongoMapper::Document key :barend

foo = Foo.new

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

foo.bar = 24# foo.bar => 24

ValidationsCurrently using fork of validatable

class Item include MongoMapper::Document

key :title, String validates_presence_of :titleend

class Item include MongoMapper::Document

key :title, String, :required => trueend

validates_presence_of validates_length_ofvalidates_format_ofvalidates_numericality_ofvalidates_acceptance_ofvalidates_confirmation_ofvalidates_inclusion_of validates_exclusion_of

CallbacksRipped from AS2’s cold, dead fingers

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 endend

: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

AssociationsI belong to you

to Docsbelongs_to, one, many, many :in

class Account include MongoMapper::Document

many :sitesend

class Site include MongoMapper::Document

key :account_id, ObjectId belongs_to :accountend

account = Account.create(:title => 'OL', :sites => [ Site.new(:title => 'OL', :domain => 'orderedlist.com'), Site.new(:title => 'RT', :domain => 'railstips.org'),])

[ { '_id' => ObjectID('...'), 'title' => 'OL', 'domain' => 'orderedlist.com' 'account_id' => ObjectID('...'), }, { '_id' => ObjectID('...'), 'title' => 'RT', 'domain' => 'railstips.org' 'account_id' => ObjectID('...'), }]

to Embedded Docsmany, one

class Item include MongoMapper::Document

many :dataend

class Datum include MongoMapper::EmbeddedDocument

key :key, String key :valueend

Item.create(:title => 'MongoSF', :data => [ Datum.new(:key => 'description', :value => 'Awesome.')])

{ '_id' => ObjectID('...'), 'title' => 'MongoSF', 'data' => [ { '_id' => ObjectID('...'), 'key' => 'description' 'value' => 'Awesome.', } ]}

UsingExtendingProphesying

PluginsConventional way to extend

Powered by PluginsMongoMapper is

associations, callbacks, clone, descendants, dirty, equality, identity_map, inspect, keys, logger, modifiers, pagination, persistence, protected, rails, serialization, timestamps, userstamps, validations

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 endend

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 endend

class Foo include MongoMapper::Document plugin ActsAsListFuend

Foo.reorder(...)Foo.new.move_to_top

Good ExampleJoint: github.com/jnunemaker/joint

class Asset include MongoMapper::Document plugin Joint

attachment :image attachment :fileend

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

asset.image.idasset.image.nameasset.image.typeasset.image.sizeasset.image.read

Descendant AppendsFancy Schmancy and Stolen

module FancySchmancy def some_method puts 'some method' endend

MongoMapper::Document.append_extensions(FancySchmancy)

class Foo include MongoMapper::Documentend

Foo.some_method # puts 'some method'Foo.new.some_method # NoMethodError

module FancySchmancy def some_method puts 'some method' endend

MongoMapper::Document.append_inclusions(FancySchmancy)

class Foo include MongoMapper::Documentend

Foo.new.some_method # puts 'some method'Foo.some_method # NoMethodError

module FancySchmancy def some_method puts 'some method' endend

class Foo include MongoMapper::Documentend

MongoMapper::Document.append_extensions(FancySchmancy)

class Bar include MongoMapper::Documentend

Foo.some_method # puts 'some method'Bar.some_method # puts 'some method'

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

MongoMapper::Document.append_inclusions(IdentityMapAddition)

UsingExtendingProphesying

Active ModelValidations, callbacks, serialization, etc.

Blank DocumentMix and match whatever you want

Mongo::QueryFancy query magic for the ruby drivergithub.com/jnunemaker/mongo-query

Ordered List

Thank you!john@orderedlist.com

John NunemakerMongoSF San Francisco, CAApril 30, 2010

@jnunemaker