MongoDB and Ruby on Rails
-
Upload
rfischer20 -
Category
Technology
-
view
18.888 -
download
2
Transcript of MongoDB and Ruby on Rails
Using MongoDB with Ruby on Rails
presented by Ryan Fischer, Founder of 20spokes
What is covered
• Why we use MongoDB and Ruby on Rails
• Choices made for Object Mapper
• Simple to get started!
Using MongoDB with Ruby on Rails
• Fast in-place updates with atomic modifiers
• Ruby on Rails is productive!
• Object Mappers available for MongoDB
• Mongo Ruby Driver
Mobile / Web
• Ruby on Rails makes REST easy, making APIs easier.
• Render responses as text, JSON, or XML
• Geospatial indexing for location based queries.
• Location-centric websites and mobile applications.
Why we chose MongoDB
• Cowrite - collaborative writing web application
• Versioning needed
• Originally using GridFS
• Travel720 - Gift registry web site
• Self contained relations can take advantage of embedding documents
Mongo Object Mappers for Ruby
• MongoMapper
• Mongoid
• Mongo ODM
• MongoModel
Why we chose Mongoid
• Excellent documentation
• Active community
• Compatibility with other projects/gems
• Similar API to ActiveRecord
• Uses ActiveValidation
• Mongoid Extras: Caching, Paranoid Documents, Versioning, Timestamping, Composite Keys
Compatible Gems with Mongoid
• Devise - Authentication solution for Rails based on Warden. Supports Mongoid out of box.
• Carrierwave - simple and flexible way to upload files from Ruby Applications. Supports grid_fs.
• Geocoder - complete geocoding solution for Rails. Adds geocoding by street or IP address, reverse geocoding, and distance queries.
• Mongoid-rspec - RSpec matchers and macros for Mongoid.
Getting Started
gem "mongoid", "~> 2.3"gem "bson_ext", "~> 1.4"
Include in Gem file
Run the install for Mongoid
rails generate mongoid:config
That’s it!
mongoid.ymldevelopment: host: localhost database: geekbusters_development
test: host: localhost database: geekbusters_test
production: host: <%= ENV['MONGOID_HOST'] %> port: <%= ENV['MONGOID_PORT'] %> username: <%= ENV['MONGOID_USERNAME'] %> password: <%= ENV['MONGOID_PASSWORD'] %> database: <%= ENV['MONGOID_DATABASE'] %> # slaves: # - host: slave1.local # port: 27018 # - host: slave2.local # port: 27019
Developing with MongoDB/Mongoid
• Generating models is the same using the console as with ActiveRecord.
• rails generate model Team name:string city:string location:array
• No migrations needed!
• Take advantage of embedded documents in models where applicable for increased performance.
• Store large files using GridFS
Fields available for Mongoid
• Array
• BigDecimal (Stored as a String)
• Boolean
• Date
• DateTime
• Float
• Hash
• Integer
• Range
• String
• Symbol
• Time
Mongoid Document
class Team include Mongoid::Document include Mongoid::Timestamps field :name, type: String field :city, type: String field :location, :type => Array validates :name, :city, :presence => true end
Persisting in the Controller
def create Team.create(:city => "New York", :name => "Giants")end
def update @team = Team.find(params[:id]) @team = Team.update_attributes(params[:team])end
Indexing
class Team include Mongoid::Document field :name, type: String index :name, unique: trueend
index( [ [ :name, MONGO::ASCENDING ] [ :city, MONGO::ASCENDING ] ] )
Indexing on multiple fields -
Indexing
To create indexes in the database use the rake task
rake db:mongoid:create_indexes
Or configure to autocreate in mongoid.yml (not recommended)
defaults: &defaults autocreate_indexes: true
Relations in Models
• Associations between models can be embedded or referenced
• NO JOINS!
• Objects that are referenced involve a separate query
• Embedded documents can be very efficient with reducing queries to one while managing the size of the document
• One to One, One to Many, and Many to Many relations available
Relations in Mongoid - Embedded
• Embedded Relations - stored inside other documents in the database.class Blog include Mongoid::Document embeds_many :postsend
class Post include Mongoid::Document embedded_in :blogend
Embedded Posts
{ "_id" : ObjectId("4e9ba47fcdffba523f000004"), "name" : "Geekbusters Blog", "posts" : [ {"content" : "Slimer is right behind you.", _id" : ObjectId("4e9ba47fcdffba523f000005")} ]}
Polymorphic Behaviorclass Image include Mongoid::Document embeds_many :comments, as: :commentableend
class Document include Mongoid::Document embeds_many :comments, as: :commentableend
class Comment include Mongoid::Document embedded_in :commentable, polymorphic: trueend
Relations in Mongoid - Referenced
class Blog include Mongoid::Document has_many :posts, dependent: :deleteend
class Post include Mongoid::Document belongs_to :blogend
Referenced Relations - stores reference to a document in another collection, typically an id
Many to Many Relationship
class Tag include Mongoid::Document has_and_belongs_to_many :postsend
class Post include Mongoid::Document has_and_belongs_to_many :tagsend
Querying
• Queries are of type Criteria, which is a chainable and lazily evaluated wrapper to a MongoDB dynamic query.
• Chainable queries include:all_in all_ofalso_in and any_ofascdescdistinctexcludes
includeslimitnearnot_inonlyorder_byskipwherewithout
Query Examples
Team.near(location: [20.70, 38.15]).limit(20)
Team.any_in(names: ["Giants", "Bears", "Lions"])
Team.find_or_create_by(name: "Giants")
Team.where(name: "Cowboys").destroy_all
Versioning with Mongoid
• Embeds a version of the object on each save.
• Can skip versioning and also set the max versions.
• Add to model -
include Mongoid::Versioning
Versioning Example{"_id" : ObjectId("4e9ba7fdcdffba52d6000004"), "content" : "Impossible. I am too loud to fall asleep to.", "created_at" : ISODate("2011-10-17T03:58:53Z"), "title" : "Impossible to sleep to - this guy.", "updated_at" : ISODate("2011-10-17T03:58:53Z"), "version" : 3, "versions" : [ {"title" : "Who is asleep?", "content" : "Wake up the guy next to you if they are asleep. Thanks.", "version" : 1, "created_at" : ISODate("2011-10-17T03:58:53Z")}, {"title" : "Who is asleep?", "content" : "Impossible. I am too loud to fall asleep to.", "created_at" : ISODate("2011-10-17T03:58:53Z"), "version" : 2 } ]}
And More
• Identity Map
• Callbacks
• Scopes
• Dirty Tracking
Testing Rails with MongoDB
• RSpec-Mongoid provides test matchers
• RSpec does not refresh the database with each test run.
• Database Cleaner to the rescue. It be setup to truncate a database before running tests. Add below after installing the DatabaseCleaner Gem.
config.before(:suite) do DatabaseCleaner.strategy = :truncation DatabaseCleaner.orm = "mongoid" end
Hosting Options
• Heroku is a widely used cloud hosting for Ruby on Rails
• MongoHQ and MongoLab both have add on options
• Options and pricing are similar