Mongoid in the real world

Post on 15-Jan-2015

5.406 views 3 download

Tags:

description

 

Transcript of Mongoid in the real world

Mongoid in the Real World

Kevin Faustino@kfaustino

http://adventuresincoding.com

Toronto Ruby BrigadeDecember 14, 2010

Thanks to our sponsors

What is Mongoid?

Object Document Mapper

Using MongoidEveryday Mongoid

Integrations

class Postend

class Post include Mongoid::Documentend

Types

class Post include Mongoid::Document include Mongoid::Timestamps

field :title field :content field :published_on, :type => DateTime field :slugend

Valid Types

Array, BigDecimal, Boolean, Date, DateTime, Float, Hash, Integer, String, Symbol, Time

Associations

class Person include Mongoid::Document field :first_name field :last_name embeds_one :addressend

class Address include Mongoid::Document field :street field :city embedded_in :person, :inverse_of => :addressend

{ "_id" : ObjectId("4d06eaa46c50a1031a000001"), "address" : { "_id" : ObjectId("4d06eade6c50a1031a000002"), "street" : "123 Liberty St.", "city" : "Toronto" }, "first_name" : "Kevin", "last_name" : "Faustino"}

class Blog include Mongoid::Document

references_many :postsend

class Post include Mongoid::Document referenced_in :blogend

{ "_id" : ObjectId("4c9f54866c50a10a75000003"), "blog_id" : ObjectId("4ca531c46c50a12d1b000002"), "content" : "What is Faraday? ...", "featured_image_filename" : "faraday.jpg", "slug" : "building-modular-http-client-code-with-faraday", "title" : "Building modular HTTP client code with Faraday",}

Validations

validates_acceptance_ofvalidates_associatedvalidates_confirmation_ofvalidates_exclusion_ofvalidates_format_ofvalidates_inclusion_ofvalidates_length_ofvalidates_numericality_ofvalidates_presence_ofvalidates_uniqueness_of

ActiveModel Validators + More

Indexing

Defining Indexes

# uniqueindex :ssn, :unique => true

# Compound indexesindex([ [ :first_name, Mongo::ASCENDING ], [ :last_name, Mongo::ASCENDING ]])

# Foreign Key indexesreferenced_in :post, :inverse_of => :comments, :index => true

Using MongoidEveryday Mongoid

Integrations

Document Limit

4 MB

Testing

RSpec Integration

# in spec/spec_helper.rbRSpec.configure do |config|

config.mock_with :rspec

config.before :each do Mongoid.master.collections.select {|c| c.name !~ /system/ }.each(&:drop) end

end

Shoulda Matchers?

Use Remarkable

# in spec/spec_helper.rbrequire 'remarkable/active_model'require 'remarkable/mongoid'

Mongoid Matchers

have_fieldreference_onereference_manybe_referenced_inembed_oneembed_manybe_embedded_invalidate_uniqueness_ofvalidate_associationAll ActiveModel validations from Remarkable::ActiveModel

Cucumber Integration

# features/support/hooks.rbBefore do |scenario| Mongoid.master.collections.select {|c| c.name !~ /system/ }.each(&:drop)end

Factory Girl

FactoryGirl.define do

factory :post do title 'My first blog post' author 'Kevin Faustino' content 'Hello World' end

end

Works out of the box

Factories with Cucumber

# features/support/env.rbrequire 'factory_girl'require 'factory_girl/step_definitions'

Monkey Patched Step Definition

# features/step_definitions/mongoid_steps.rbGiven /^an? (.+) exists with an? (.+) of "([^"]*)"$/ do |model, field, value| factory_name = model.gsub(' ', '_') Factory factory_name, field => valueend

Example Feature Usage

Given the following posts exist: | title | excerpt | | 10 greatest Batman Villians | We countdown ... | | The Death of Batman | Batman falls ... |

Caching in Rails

Create a Cache-Key

module Cacheable def cache_key if new_record? "#{collection_name}/#{id}/new" elsif respond_to?(:updated_at) "#{collection_name}/#{id}-#{updated_at.to_i}" else "#{collection_name}/#{id}" end end end

Safe Operations

post = Post.safely(:w => 2).create( :title => 'We will receive verification')post.safely(:w => 2).destroy

:w - A client can block until a write operation has been replicated to N servers

:fsync - force the database to fsync all files before returning

Safely Options

Enslave

# Query specificPost.where(:title => 'Toronto Ruby').enslave

# Document specificclass Post include Mongoid::Document enslaveend

Query from your Slaves

Dropping Down

When you need more performance, drop down

to the driver

# Add a post id only if it does not already exist on # the setcollection.update({'_id' => id}, {'$addToSet' => {'post_ids' => post.id}})

collection = mongo-ruby-driver

Using MongoidEveryday Mongoid

Integrations

Full Text-Search

@solr = RSolr.connect :url => "http://127.0.0.1:8983/solr"@solr.add( { :id => post.id, :text => post.content, :published_on => post.published_on.strftime("%Y-%m-%dT%H:%M:00Z") }, { :add_attributes => { :commitWithin => 10000 } })

Use Solr

Photo Uploads

Not with paperclip!

X

Agnostic

class Post include Mongoid::Document include Mongoid::Timestamps

field :title field :author field :content field :slug referenced_in :blog mount_uploader :featured_image, ImageUploaderend

Document Example

Authentication

class User include Mongoid::Document devise :database_authenticatable, :rememberable, :trackable, :validatable

end

Use Devise

Coming Soon

Many to Many support without dropping down

to the driver

Thank you!