using mongoid with ruby on rails
TRANSCRIPT
![Page 1: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/1.jpg)
Schema-less Design An introduction to the Mongoid ODM
![Page 2: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/2.jpg)
1. MongoDB
2. Mongoid ODM compares to ORM/SQL
3. Modelling Bitmaker Rainforest app without ActiveRecord
4. Going further
5. Conclusion
Overview
![Page 3: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/3.jpg)
Questions going in• What is MongoDB?
• How does it compare from SQL-based databases?
• What does schema-less entail?
• How does ODM compare with ORM? Rainforest tutorial
• Worth it?
![Page 4: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/4.jpg)
Object Document Mapper (ODM)
Translate between objects in code and document representation of data.
Object Relational Mapping translates between objects in code the the relational representation of the data.
![Page 5: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/5.jpg)
MongoDB• Open-source database
• NoSQL (cluster friendly, 21st-century web, non-relational, schema-less)
• Data is stored in collections and documents whereas in SQL data is stored in tables and rows
• JSON-like structure to documents
![Page 6: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/6.jpg)
Differs from SQL
No JOINS -> run two or more queries
Embed and Referencing of document/data objects
Fast querying
PostgreSQL has strict schema / MongoDB has implicit schema
![Page 7: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/7.jpg)
Use cases
“Big Data” - large and unwieldy
90% of business data is unstructured
Increasing volume, variety and velocity
craigslist, Forbes, New York Times, Foursquare, etc.
![Page 8: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/8.jpg)
The SetupInstall mongodb
https://docs.mongodb.org/manual/installation/
Run mongo server and mongo database in separate terminal tabs
![Page 9: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/9.jpg)
~>rails new rainforest —skip-active-record
The Setup
Removes ActiveRecord from the application No schema.rb No migrations folder
gem 'mongoid', '~> 5.1'
~>bundle install
~>rails generate mongoid:configcreates config/mongoid.yml
![Page 10: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/10.jpg)
application.rb
require File.expand_path('../boot', __FILE__)
require "rails" # Pick the frameworks you want: require "active_model/railtie" require "active_job/railtie" # require "active_record/railtie" require "action_controller/railtie" require "action_mailer/railtie" require "action_view/railtie" require "sprockets/railtie" require "rails/test_unit/railtie"
. . .
![Page 11: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/11.jpg)
mongoid.yml
development: # Configure available database clients. (required) clients: # Defines the default client. (required) default: # Defines the name of the default database that Mongoid can connect to. # (required). database: rainforest_development # Provides the hosts the default client can connect to. Must be an array # of host:port pairs. (required) hosts: - localhost:27017 options: # Change the default write concern. (default = { w: 1 }) # write: # w: 1
![Page 12: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/12.jpg)
Rainforest Appclass Product include Mongoid::Document field :name, type: String field :description, type: String field :price_in_cents, type: Integer . . .
embeds_many :reviews embeds_one :category end
class Category include Mongoid::Document field :name, type: String
embedded_in :product end
![Page 13: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/13.jpg)
Product Controller
class ProductsController < ApplicationController . . . def product_params params.require(:product).permit(:name, :description, :price_in_cents, {category: [:category_id, :name]}) end end
![Page 14: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/14.jpg)
Rainforest Appclass User include Mongoid::Document field :name, type: String field :email, type: String field :password, type: String . . . has_many :products
end
class Review include Mongoid::Document field :comment, type: String
field :user_id, type: BSON::ObjectId . . . embedded_in :product end
![Page 15: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/15.jpg)
RelationsMongoid ODM associations similar to ActiveRecord ORM
Association is not just for Relational Mappers
Embeds One, Embeds Many, Has One, Has Many, Has And Belongs To Many, counter_cache (cache the counts of an associated model)
No has_many :through
![Page 16: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/16.jpg)
BSON Objects
BSON: supports embedding of objects within arrays
Allow for extensions not part of JSON spec
Minimum overhead
Traverse quickly (fast to encode and decode)
![Page 17: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/17.jpg)
{"_id" : ObjectId("5728b57b370d93124e000000"),"name" : "Day planner","description" : "Schedule events","price_in_cents" : 1299,"user_id" : ObjectId("5727b3b0370d93009d000000"),"category" : {
"_id" : ObjectId("5728b57b370d93124e000001"),"name" : “Office material"
},"reviews" : [
{"_id" : ObjectId("5728b5a3370d93124e000002"),"comment" : "A great product","user_id" : ObjectId("5727b3b0370d93009d000000")
}
![Page 18: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/18.jpg)
[1] pry(main)> Product.first#<Product:0x007fc1290cd108> { :_id => BSON::ObjectId('56b54bc3370d93d2d5411757'), :category => { "_id" => BSON::ObjectId('570c78f1370d936468000000'), "name" => "Electronics" }, :description => "Listen to music without all the hassle of a cord.", :name => "Wireless Headphones", :price_in_cents => 60, :reviews => [ [0] { "_id" => BSON::ObjectId('56b54e59370d93d3b4fe9848'), "comment" => "Test comment”,
"user_id" => BSON::ObjectId('56eb9d92370d937950d21463 }, [1] { "_id" => BSON::ObjectId('56b54e5f370d93d3b4fe9849'), "comment" => "Checking comment\r\n”, "user_id" => BSON::ObjectId('56eb9d92370d937950d21463 }, [2] { "_id" => BSON::ObjectId('56b54e6d370d93d3b4fe984a'), "comment" => "Just bought these headphones.”, "user_id" => BSON::ObjectId('56eb9d92370d937950d21463 }, [0] { "_id" => BSON::ObjectId('5706dc66370d934ccd000000'), "comment" => "Checking embedded review", "user_id" => BSON::ObjectId('56eb9d92370d937950d21463') } ]}
![Page 19: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/19.jpg)
Rails Console[3] pry(main)> products = Product.all#<Mongoid::Criteria selector: {} options: {} class: Product embedded: false>
The query doesn’t run until the data is requested
![Page 20: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/20.jpg)
[6] pry(main)> products.each {|product|puts product.name }Wireless HeadphonesChromecast for TVFerrariATMComputerFerrari2Game BoySony HeadphonesSpeakersCarDell ComputerSamsung TelevisionAudi ConvertibleSnowmobile#<Mongoid::Contextual::Mongo:0x007fc129167550 @cache=nil, @klass=Product, @criteria=#<Mongoid::Criteria selector: {} options: {} class: Product embedded: false>, @collection=#<Mongo::Collection:0x70233797373000 namespace=rainforest_development.products>, @view=#<Mongo::Collection::View:0x70233797372780 namespace='rainforest_development.products @selector={} @options={}>, @cache_loaded=true>
![Page 21: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/21.jpg)
Implicit schema
[9] pry(main)> product[:model] = "TS2-3Q78"
[8] pry(main)> product = Product.first
![Page 22: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/22.jpg)
[1] pry(main)> Product.first#<Product:0x007fc1290cd108> { :_id => BSON::ObjectId('56b54bc3370d93d2d5411757'), :category => { "_id" => BSON::ObjectId('570c78f1370d936468000000'), "name" => "Electronics" }, :description => "Listen to music without all the hassle of a cord.", :model => "TS2-3Q78", :name => "Wireless Headphones", :price_in_cents => 60, :reviews => [ [0] { "_id" => BSON::ObjectId('56b54e59370d93d3b4fe9848'), "comment" => "Test comment" }, [1] { "_id" => BSON::ObjectId('56b54e5f370d93d3b4fe9849'), "comment" => "Checking comment\r\n" }, [2] { "_id" => BSON::ObjectId('56b54e6d370d93d3b4fe984a'), "comment" => "Just bought these headphones." }, [3] { "_id" => BSON::ObjectId('5706dc66370d934ccd000000'), "comment" => "Checking embedded review", "user_id" => BSON::ObjectId('56eb9d92370d937950d21463') } ]}
![Page 23: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/23.jpg)
Mongoid
Similar syntax to ActiveRecord - associations, datatypes, etc.
No need for migrations
Great documentation; active community
Popular gems have mongoid counterpart (Devise, carrierwave-mongoid, mongoid-paperclip, geocoder, mongoid-rspec)
Setup is fast and mistakes quickly fixed (no rollbacks)
![Page 24: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/24.jpg)
class Product include Mongoid::Document include Mongoid::Paperclip . . .
has_mongoid_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: lambda { |image| ActionController::Base.helpers.asset_path('missing.png') }
validates_attachment_content_type :avatar,:content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
end
class ProductsController < ApplicationController . . . def product_params params.require(:product).permit(:name, :description, :price_in_cents, :avatar, {category: [:category_id, :name]}) end
![Page 25: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/25.jpg)
#<Product:0x007fc12b0db148> { :_id => BSON::ObjectId('570c32f9370d935b78000000'), :avatar_content_type => "image/jpeg", :avatar_file_name => "snowmobile.jpeg", :avatar_file_size => 7081, :avatar_fingerprint => "33234414813b3e3bf8a26281a2d7316f", :avatar_updated_at => 2016-04-12 00:56:31 UTC, :category => { "_id" => BSON::ObjectId('570c32f9370d935b78000001'), "name" => "Automobile" }, :description => "For northern living", :name => "Snowmobile", :price_in_cents => 345436 }
![Page 26: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/26.jpg)
Going further• Indexing
• Map/Reduce to condense large volumes of data; work around for JOINS - rearrange data into aggregate forms
• Sharding
• Track data versioning
• GeoSpatial indexing
![Page 27: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/27.jpg)
Worth it?• It depends what you want
• Have MongoDB serve up user info or cache preferences, integrate with social networks; SQL to handle payments/ordering
• Great for searching large amounts of data.
• PostgreSQL JSON type - support for arbitrary attributes (WARNING: anti-pattern)
• For this application, mongoid can work and clarified features for me, but SQL and Schema-based design seem optimized for this case
• Different ways to organize data and design models
• Learned some new things about ActiveRecord and PostgreSQL
![Page 28: Using Mongoid with Ruby on Rails](https://reader034.vdocument.in/reader034/viewer/2022051521/586f85ac1a28ab54768b5193/html5/thumbnails/28.jpg)
Sourceshttps://www.mongodb.com/nosql-explained
Rege, Gautam. Ruby and MongoDB Web Development Beginner’s Guide, Packt Publishing, 2012
http://www.sarahmei.com/blog/2013/11/11/why-you-should-never-use-mongodb/ comment-page-1/
https://www.mongodb.com/compare/mongodb-mysql
https://github.com/meskyanichi/mongoid-paperclip
https://gorails.com/guides/setting-up-rails-4-with-mongodb-and-mongoid
https://gorails.com/blog/rails-4-0-with-mongodb-and-mongoid
http://stackoverflow.com/questions/26182890/perform-atomic-block-transactions-in-rails-with-mongoid
http://blog.2ndquadrant.com/postgresql-anti-patterns-unnecessary-jsonhstore-dynamic-columns/