O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

The Ruby/mongoDB ecosystem

4.559 visualizações

Publicada em

Publicada em: Tecnologia
  • Seja o primeiro a comentar

The Ruby/mongoDB ecosystem

  1. 1. The Ruby / MongoDB ecosystem Harold Giménez Mongo Boston - Sept 20, 2010
  2. 2. Harold Giménez @hgimenez thoughtbot, inc.
  3. 3. Why Ruby? • Expressiveness, Elegance • Powerful • Simple, flexible syntax • Open Source • Community • Library support: rubygems
  4. 4. ...maybe too many libraries
  5. 5. mongo-ruby-driver http://github.com/mongodb/mongo-ruby-driver
  6. 6. Start here Closest to mongo’s lingo, almost-native query syntax require 'mongo' db = Mongo::Connection.new.db('mongo-boston') people = db.collection('people') people.insert({'name' => 'Harold', 'address' => { 'city' => 'Boston' } }) people.insert({'name' => 'Jack'}) people.find('name' => 'Harold').to_a people.find('address.city' => 'Boston').to_a
  7. 7. Tools mongoid Mongomatic MongoMapper MongoODM connection, cursor, CRUD mongo-ruby-driver
  8. 8. mongoid http://github.com/mongoid/mongoid
  9. 9. class Person include Mongoid::Document field :cool_dude, :type => Boolean, :default => false field :name field :age, :type => Integer embeds_one :address validates_presence_of :name end class Address include Mongoid::Document field :city field :zip_code embedded_in :person, :inverse_of => :address end
  10. 10. class Person include Mongoid::Document field :cool_dude, :type => Boolean, :default => false field :name field :age, :type => Integer embeds_one :address embeds_many references_one validates_presence_of :name references_many end referenced_in class Address include Mongoid::Document field :city field :zip_code embedded_in :person, :inverse_of => :address end
  11. 11. > me = Person.create!(:cool_dude => true) Mongoid::Errors::Validations: Validation failed - Name can't be blank. > me = Person.create(:name => 'Harold', :cool_dude => true) => #<Person name: "Harold", _id: BSON::ObjectId('4c950d73fff2cb4262000007'), cool_dude: true> > me.address = Address.new(:city => 'Boston') => #<Address city: "Boston", zip_code: nil, _id: BSON::ObjectId('4c950d83fff2cb4262000008')> > me.save { "_id" : ObjectId("4c950d73fff2cb4262000007"), "address" : { "_id" : ObjectId("4c950d83fff2cb4262000008"), "city" : "Boston", "zip_code" : null }, "name" : "Harold", "cool_dude" : true }
  12. 12. mongoid criteria me = Person.create(:name => 'Harold', :cool_dude => true) another_harold = Person.create(:name => 'Harold') someone_else = Person.create(:name => 'Jack', :cool_dude => true) Person.where(:name => 'Harold') Person.where(:cool_dude => true) Person.where(:name => 'Harold').where(:cool_dude => true) class Person def self.cool_dudes where(:cool_dude => true) end def self.harolds where(:name => 'Harold') end end Person.cool_dudes.harolds Person.harolds.not_in("address.city" => ["Boston"]).asc("address.city")Person.cool_dudes.only(:id).where("address. city" => "Boston")
  13. 13. more querying Person.all_in(:name => [ "Harold", "Ha, Lord!" ]) Person.any_in(:status => ["Single", "Divorced", "Separated"]) Person.any_of({ :name => "Harold" }, { :cool_dude => true }) Person.and(:name => "Harold", :cool_dude => false) Person.excludes("address.city" => "Boston") Person.limit(20) Person.not_in(:name => ["Harold", "Jack"]) Person.where(:address.exists => true) Person.where(:age.gt => 21) Person.where(:age.gte => 21) Person.where(:age.lt => 30) Person.where(:age.lte => 30)
  14. 14. Mongoid::Paranoia class Person include Mongoid::Document include Mongoid::Paranoia end person.delete # person.deleted_at = Time.now person.restore # phew! person.delete! person.restore # it's gone :(
  15. 15. cursor proxy module Mongoid class Cursor include Enumerable OPERATIONS = [ :close, :closed?, :count, :explain, :fields, :full_collection_name, :hint, :limit, :order, :query_options_hash, :query_opts, :selector, :skip, :snapshot, :sort, :timeout ] OPERATIONS.each do |name| define_method(name) { |*args| @cursor.send(name, *args) } end def each # ... end def next_document # ... end def to_a # ... end end
  16. 16. Enables caching vs. lazy loading of big datasets Person.all.cache.each { |person| person.hug } or class Person include Mongoid::Document cache end Person.all.each { |person| person.hug }
  17. 17. ActiveModel under the hood ActiveModel::Conversion ActiveModel::Naming ActiveModel::Serialization ActiveModel::MassAssignmentSecurity ActiveModel::Translation ActiveModel::Validation ActiveModel::Callbacks
  18. 18. MongoMapper http://github.com/jnunemaker/mongomapper
  19. 19. class Person include MongoMapper::Document key :cool_dude, Boolean, :default => false key :name, String, :required => true key :age, Integer one :address end class Address include MongoMapper::EmbeddedDocument key :city, String key :zip_code, String end
  20. 20. class Person include MongoMapper::Document key :cool_dude, Boolean, :default => false key :name, String, :required => true key :age, Integer one :address many end belongs_to class Address include MongoMapper::EmbeddedDocument key :city, String key :zip_code, String end
  21. 21. class Person include MongoMapper::Document key :cool_dude, Boolean, :default => false key :name, String, :required => true key :age, Integer one :address end class Address include MongoMapper::EmbeddedDocument key :city, String key :zip_code, String end
  22. 22. class Person include MongoMapper::Document key :cool_dude, Boolean, :default => false key :name, String, :required => true key :age, Integer one :address Alternative end validation syntax class Address include MongoMapper::EmbeddedDocument key :city, String key :zip_code, String end
  23. 23. > me = Person.create!(:cool_dude => true) MongoMapper::DocumentNotValid: Validation failed: Name can't be empty > me = Person.create(:name => 'Harold', :cool_dude => true) => #<Person name: "Harold", _id: BSON::ObjectId('4c9508fbfff2cb4096000007'), cool_dude: true> > me.address = Address.new(:city => 'Boston') => #<Address city: "Boston", zip_code: nil, _id: BSON::ObjectId('4c950911fff2cb4096000008')> > me.save { "_id" : ObjectId("4c9508fbfff2cb4096000007"), "address" : { "_id" : ObjectId("4c950911fff2cb4096000008"), "city" : "Boston", "zip_code" : null }, "name" : "Harold", "cool_dude" : true }
  24. 24. Plugin architecture module MongoMapper module Plugins def plugins @plugins ||= [] end def plugin(mod) extend mod::ClassMethods if mod.const_defined?(:ClassMethods) include mod::InstanceMethods if mod.const_defined?(:InstanceMethods) mod.configure(self) if mod.respond_to?(:configure) plugins << mod end end end associations, dirty, document dynamic_querying, embedded_document, equality indexes, logger modifiers, pagination persistence, protected, querying safe, SCI, scopes, serialization, validations, and more (pretty much everything in MM)
  25. 25. Querying (plucky) Person.where(:address.exists => true).all Person.where(:age.gt => 21).limit(10).all Person.where(:age.gte => 21).all Person.where(:age.lt => 30).all Person.where(:age.lte => 30).all ( Similar to mongoid’s querying and scoping ) Except for no support for #not_in, #exists, #any_of and others found in mongoid
  26. 26. Notable difference: mongoid MongoMapper #<Mongoid::Criteria: Person.where(:name => 'Harold') 0x101754bd8 @klass=Person, #<Plucky::Query name: @options={}, @documents=[], "Harold"> @selector={:name=>"Harold"}> #<Mongoid::Criteria: 0x101754bd8 @klass=Person, Person.where(:name => 'Harold').all @options={}, @documents=[], [#<Person name: "Harold"] @selector={:name=>"Harold"}> Person.where(:name => 'Harold').all.to_a [#<Person name: "Harold"] [#<Person name: "Harold"] or #each, #map, etc
  27. 27. cache_key class Person include MongoMapper::Document end Person.new.cache_key # => "Person/new" Person.create.cache_key # => "Person/4c9508fbfff2cb4096000007"
  28. 28. Custom data types class MongoSet def self.to_mongo(value) value.to_a end def self.from_mongo(value) Set.new(value || []) end end class Person include MongoMapper::Document key :aliases, MongoSet end
  29. 29. Typecasting class Person include MongoMapper::Document key :friend_ids, Array, :typecast => 'ObjectId' end Person.new(:friend_ids => %w(4c950520fff2cb3fb9000004 4c950558fff2cb3fb9000005 4c950911fff2cb4096000008) )
  30. 30. Both MongoMapper and Mongoid provide: #cache_key Cursor wrapper/cache plugins embraces ActiveModel custom data types thorough query syntax abstraction typecasting Persistance Querying Associations Embedded Docs Serialization Dynamic Finders Pagination Scopes Rails 3
  31. 31. Rails 2, you are... ing oy t nn no , a ’s ly at g h re u e in t yw he .th us an .. o c ing go e! MongoMapper m d to .d ea .. Mongoid
  32. 32. MongoODM http://github.com/carlosparamio/mongo_odm Mongomatic MongoMapper http://github.com/benmyles/mongomatic
  33. 33. A fresh look Query chaining Lazy loading Validations Callbacks Rails integration Worth keeping an eye on!
  34. 34. Mongoid MongoMapper Side by side! Mongomatic MongoODM
  35. 35. Number of Files 300 250 200 project mongoid files MongoMapper mongomatic 150 MongoODM 100 50 May−09 Aug−09 Nov−09 Feb−10 May−10 Aug−10 day
  36. 36. Number of Lines 30000 number_of_lines project mongoid 20000 MongoMapper mongomatic MongoODM 10000 0 May−09 Aug−09 Nov−09 Feb−10 May−10 Aug−10 day
  37. 37. Number of Collaborators 80 60 project collaborators mongoid MongoMapper mongomatic 40 MongoODM 20 0 May−09 Aug−09 Nov−09 Feb−10 May−10 Aug−10 day
  38. 38. Number of Commits 1500 project 1000 mongoid commits MongoMapper mongomatic MongoODM 500 0 May−09 Aug−09 Nov−09 Feb−10 May−10 Aug−10 day
  39. 39. mongoid release cycle 25 20 prior_days 15 10 5 0 2.0.0.beta.102.0.0.beta1v0.0.1 v0.10.5v0.11.4v0.12.0 v0.2.5v0.3.2v0.4.2v0.4.8v0.5.2v0.5.7 v0.6.2v0.6.7 v0.7.2v0.7.7 v0.8.2v0.8.7 v0.9.11 v0.9.6v1.0.1v1.0.6v1.1.4 v1.2.13 v1.2.5v1.9.0 2.0.0.beta.11 2.0.0.beta11v0.10.2v0.11.1v0.11.7 v0.2.2v0.2.7v0.3.4v0.4.4v0.5.1v0.5.4v0.5.9v0.6.3v0.6.8 v0.7.3v0.7.8 v0.8.3v0.8.8 v0.9.12 v0.9.7v1.0.2v1.1.0v1.2.0 v1.2.14 v1.2.6v1.9.1 2.0.0.beta.12 2.0.0.beta2 v0.10.3v0.11.2v0.11.8 v0.2.3v0.3.0v0.4.0v0.4.5 v0.5.11 v0.5.8 v0.6.4v0.6.9 v0.7.4v0.7.9 v0.8.4v0.8.9 v0.9.2 v0.9.8v1.0.3v1.1.1v1.2.1 v1.2.15 v1.2.7v2.0.0 2.0.0.beta.13 2.0.0.beta7 v0.10.4v0.11.3v0.11.9 v0.2.4v0.3.1v0.4.1v0.4.7 v0.5.3 v0.6.0 v0.6.5v0.7.0 v0.7.5v0.8.0 v0.8.5v0.9.0 v0.9.3 v0.9.9v1.0.4v1.1.2 v1.2.11 v1.2.3v1.2.8 2.0.0.beta.14 2.0.0.beta8 v0.10.6v0.11.5 v0.2.0 v0.2.6v0.3.3v0.4.3v0.5.0 v0.5.5 v0.6.1 v0.6.6v0.7.1 v0.7.6v0.8.1 v0.8.6v0.9.1 v0.9.4 v1.0.0v1.0.5v1.1.3 v1.2.12 v1.2.4v1.2.9 2.0.0.beta.16 2.0.0.beta9 v0.11.0v0.11.6 v0.2.1 2.0.0.beta.17 2.0.0.beta.7 2.0.0.beta.8 v0.10.0 2.0.0.beta.9 v0.10.1 2.0.0.beta10 v0.5.10 v0.5.6 v0.6.10 v0.7.10 v0.8.10 v0.9.10 v0.9.5 v1.2.10 v1.2.2 v2.0.0.beta1 v2.0.0.beta3 v2.0.0.beta4 tag
  40. 40. MongoMapper release cycle 50 40 30 prior_days 20 10 0 v0.1.0 v0.1.2 v0.3.0 v0.3.2 v0.3.4 v0.4.0 v0.4.2 v0.5.1 v0.5.3 v0.5.5 v0.5.7 v0.6.0 v0.6.10 v0.6.3 v0.6.5 v0.6.7 v0.6.9 v0.7.1 v0.7.3 v0.7.5 v0.8.0 v0.8.2 v0.8.4 v0.1.1 v0.2.0 v0.3.1 v0.3.3 v0.3.5 v0.4.1 v0.5.0 v0.5.2 v0.5.4 v0.5.6 v0.5.8 v0.6.1 v0.6.2 v0.6.4 v0.6.6 v0.6.8 v0.7.0 v0.7.2 v0.7.4 v0.7.6 v0.8.1 v0.8.3 tag
  41. 41. the end

×