Slide 1

Slide 1 text

Using MongoDB with Ruby on Rails presented by Ryan Fischer, Founder of 20spokes

Slide 2

Slide 2 text

What is covered • Why we use MongoDB and Ruby on Rails • Choices made for Object Mapper • Simple to get started!

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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.

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

Mongo Object Mappers for Ruby • MongoMapper • Mongoid • Mongo ODM • MongoModel

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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.

Slide 9

Slide 9 text

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!

Slide 10

Slide 10 text

mongoid.yml development: 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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

Fields available for Mongoid • Array • BigDecimal (Stored as a String) • Boolean • Date • DateTime • Float • Hash • Integer • Range • String • Symbol • Time

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

Indexing class Team include Mongoid::Document field :name, type: String index :name, unique: true end index( [ [ :name, MONGO::ASCENDING ] [ :city, MONGO::ASCENDING ] ] ) Indexing on multiple fields -

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

Relations in Mongoid - Embedded • Embedded Relations - stored inside other documents in the database. class Blog include Mongoid::Document embeds_many :posts end class Post include Mongoid::Document embedded_in :blog end

Slide 19

Slide 19 text

Embedded Posts { "_id" : ObjectId("4e9ba47fcdffba523f000004"), "name" : "Geekbusters Blog", "posts" : [ {"content" : "Slimer is right behind you.", _id" : ObjectId("4e9ba47fcdffba523f000005")} ] }

Slide 20

Slide 20 text

Polymorphic Behavior class Image include Mongoid::Document embeds_many :comments, as: :commentable end class Document include Mongoid::Document embeds_many :comments, as: :commentable end class Comment include Mongoid::Document embedded_in :commentable, polymorphic: true end

Slide 21

Slide 21 text

Relations in Mongoid - Referenced class Blog include Mongoid::Document has_many :posts, dependent: :delete end class Post include Mongoid::Document belongs_to :blog end Referenced Relations - stores reference to a document in another collection, typically an id

Slide 22

Slide 22 text

Many to Many Relationship class Tag include Mongoid::Document has_and_belongs_to_many :posts end class Post include Mongoid::Document has_and_belongs_to_many :tags end

Slide 23

Slide 23 text

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_of also_in and any_of asc desc distinct excludes includes limit near not_in only order_by skip where without

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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 } ] }

Slide 27

Slide 27 text

And More • Identity Map • Callbacks • Scopes • Dirty Tracking

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

Thanks!! Email: ryan.fi[email protected] Twitter: @ryanfischer20 Check out Geekbusters on Github