Mongo mapper

Preview:

DESCRIPTION

 

Citation preview

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