MongoDB and Ruby on Rails


Published on

Published in: Technology

MongoDB and Ruby on Rails

  1. 1. Using MongoDB with Ruby on Rails presented by Ryan Fischer, Founder of 20spokes
  2. 2. What is covered• Why we use MongoDB and Ruby on Rails• Choices made for Object Mapper• Simple to get started!
  3. 3. 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
  4. 4. 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.
  5. 5. 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
  6. 6. Mongo Object Mappers for Ruby • MongoMapper• Mongoid• Mongo ODM• MongoModel
  7. 7. 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
  8. 8. 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.
  9. 9. Getting StartedInclude in Gem file gem "mongoid", "~> 2.3" gem "bson_ext", "~> 1.4"Run the install for Mongoid rails generate mongoid:configThat’s it!
  10. 10. mongoid.ymldevelopment: host: localhost database: geekbusters_developmenttest: host: localhost database: geekbusters_testproduction: 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
  11. 11. 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
  12. 12. Fields available for Mongoid • Array • Range• BigDecimal (Stored as a String) • String• Boolean • Symbol• Date • Time• DateTime• Float• Hash• Integer
  13. 13. Mongoid Documentclass Team include Mongoid::Document include Mongoid::Timestamps field :name, type: String field :city, type: String field :location, :type => Array validates :name, :city, :presence => trueend
  14. 14. Persisting in the Controllerdef create Team.create(:city => "New York", :name => "Giants")enddef update @team = Team.find(params[:id]) @team = Team.update_attributes(params[:team])end
  15. 15. Indexing class Team include Mongoid::Document field :name, type: String index :name, unique: true endIndexing on multiple fields -index( [ [ :name, MONGO::ASCENDING ] [ :city, MONGO::ASCENDING ] ])
  16. 16. IndexingTo create indexes in the database use the rake task rake db:mongoid:create_indexesOr configure to autocreate in mongoid.yml (not recommended) defaults: &defaults autocreate_indexes: true
  17. 17. 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
  18. 18. 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
  19. 19. Embedded Posts{ "_id" : ObjectId("4e9ba47fcdffba523f000004"), "name" : "Geekbusters Blog", "posts" : [ {"content" : "Slimer is right behind you.", _id" : ObjectId("4e9ba47fcdffba523f000005")} ]}
  20. 20. Polymorphic Behaviorclass Image include Mongoid::Document embeds_many :comments, as: :commentableendclass Document include Mongoid::Document embeds_many :comments, as: :commentableendclass Comment include Mongoid::Document embedded_in :commentable, polymorphic: trueend
  21. 21. Relations in Mongoid - ReferencedReferenced Relations - stores reference to a document in another collection,typically an idclass Blog include Mongoid::Document has_many :posts, dependent: :deleteendclass Post include Mongoid::Document belongs_to :blogend
  22. 22. Many to Many Relationshipclass Tag include Mongoid::Document has_and_belongs_to_many :postsendclass Post include Mongoid::Document has_and_belongs_to_many :tagsend
  23. 23. Querying• Queries are of type Criteria, which is a chainable and lazily evaluated wrapper to a MongoDB dynamic query.• Chainable queries include: all_in includes all_of limit also_in near and not_in any_of only asc order_by desc skip distinct where excludes without
  24. 24. Query ExamplesTeam.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
  25. 25. 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
  26. 26. 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 } ]}
  27. 27. And More• Identity Map• Callbacks• Scopes• Dirty Tracking
  28. 28. 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
  29. 29. 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
  30. 30. Thanks!!Email: ryan.fischer@20spokes.comTwitter: @ryanfischer20Check out Geekbusters on Github