Date post: | 15-Jan-2015 |
Category: |
Documents |
Upload: | kevin-faustino |
View: | 5,405 times |
Download: | 3 times |
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!