Uma Breve Introdução ao MongoDB

1,526 views

Published on

Esta apresentação faz uma rápida introdução ao uso de uma base de dados orientada a documentos, mostrando o mapeamento SQL para Mongo, o Driver Ruby para MongoDB e um ODM para Mongo, o Mongoid.

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,526
On SlideShare
0
From Embeds
0
Number of Embeds
57
Actions
Shares
0
Downloads
59
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Uma Breve Introdução ao MongoDB

  1. 1. Eduardo Nicola F. Zagari
  2. 2. Sumário <ul><li>MongoDB </li></ul><ul><ul><li>Característica </li></ul></ul><ul><ul><li>Instalação </li></ul></ul><ul><ul><li>Mapeamento SQL  MongoDB </li></ul></ul><ul><ul><li>Conexão com Banco via shell </li></ul></ul><ul><ul><li>Schema Dinâmico </li></ul></ul><ul><ul><li>Inserção de dados </li></ul></ul><ul><ul><li>Interando sobre a coleção </li></ul></ul><ul><ul><li>Sintaxe </li></ul></ul>
  3. 3. Sumário <ul><li>MongoDB Ruby Driver </li></ul><ul><ul><li>Instalação </li></ul></ul><ul><ul><li>Conexão com banco </li></ul></ul><ul><ul><li>Listagem de bases e coleções </li></ul></ul><ul><ul><li>Criação/acesso de coleções </li></ul></ul><ul><ul><li>Inserção de documentos </li></ul></ul><ul><ul><li>Atualização de documentos </li></ul></ul><ul><ul><li>Busca </li></ul></ul><ul><ul><li>Índices </li></ul></ul>
  4. 4. Sumário <ul><li>Mongoid </li></ul><ul><ul><li>Instalação </li></ul></ul><ul><ul><li>Documentos </li></ul></ul><ul><ul><li>Persistência </li></ul></ul><ul><ul><li>Querying </li></ul></ul><ul><ul><li>Relations </li></ul></ul>
  5. 5. Características <ul><li>Armazenamento Orientado a Documentos </li></ul><ul><li>Suporte full-index </li></ul><ul><li>Replicação e Alta disponibilidade </li></ul><ul><li>Auto sharding </li></ul><ul><li>Querying </li></ul><ul><li>Atualizações rápidas in-place </li></ul><ul><li>Map/Reduce </li></ul><ul><li>GridFS </li></ul>
  6. 6. Instalando MongoDB <ul><li>Download </li></ul><ul><li>Crie o diretório de dados </li></ul>$ curl http://downloads.mongodb.org/osx/mongodb-osx-i386-x.y.z.tgz > mongo.tgz $ tar xzf mongo.tgz $ sudo mkdir –p /data/db $ sudo chmod 777 /data/db
  7. 7. Instalação MongoDB <ul><li>Inicie o servidor e se conecte a ele </li></ul><ul><li>Em uma shell </li></ul><ul><li>Em outra shell </li></ul>$ ./mongodb-XXXXXXX /bin/mongod <ul><li>$ ./mongodb-XXXXXXX /bin/mongo </li></ul><ul><li>db.foo.save( { a : 1 } ) </li></ul><ul><li>{ &quot;_id&quot; : ObjectId(&quot;4e46f2141373c8f77f7ee954&quot;), &quot;a&quot; : 1 } </li></ul>
  8. 8. Mapeamento SQL  MongoDB
  9. 9. Conexão com Banco via shell <ul><li>Inicie a shell do MongoDB </li></ul><ul><li>Para trocar de base, tecle </li></ul>$ /Applications/mongodb-osx-x86_64-1.8.2/bin/mongo MongoDB shell version: 1.8.2 connecting to: test > use mydb switched to db mydb > show dbs admin (empty) local (empty) test 0.203125GB
  10. 10. Schema Dinâmico (Schema Free) <ul><li>MongoDB possui databases, collections e índices </li></ul><ul><li>Collections contêm documentos BSON </li></ul><ul><li>Documentos BSON possuem campos </li></ul><ul><ul><li>Sem pré-definição </li></ul></ul><ul><ul><li>Sem schemas </li></ul></ul><ul><ul><li>Não há a noção de “ALTER table” </li></ul></ul><ul><ul><li>Na prática, é comum uma coleção possuir estrutura de documentos homogênea, no entanto, isto não é um requisito </li></ul></ul>
  11. 11. Inserção de Dados > j = { name : &quot;mongo&quot; }; {&quot;name&quot; : &quot;mongo&quot;} > t = { x : 3 }; { &quot;x&quot; : 3 } > db.things.save(j); > db.things.save(t); > db.things.find(); { &quot;_id&quot; : ObjectId(&quot; 4e47fae21373c8f77f7ee955 &quot;), &quot;name&quot; : &quot;mongo&quot; } { &quot;_id&quot; : ObjectId(&quot; 4e47faeb1373c8f77f7ee956 &quot;), &quot;x&quot; : 3 } <ul><li>Sem pré-definição do collection </li></ul><ul><li>Lazy initialization </li></ul><ul><li>Docs com camps distintos </li></ul><ul><li>Atribuição do campo “_id </li></ul>
  12. 12. Inserção de mais dados > for (var i = 1; i <= 20; i++) db.things.save({x : 4, j : i}); > db.things.find() { &quot;_id&quot; : ObjectId(&quot;4e47fae21373c8f77f7ee955&quot;), &quot;name&quot; : &quot;mongo&quot; } { &quot;_id&quot; : ObjectId(&quot;4e47faeb1373c8f77f7ee956&quot;), &quot;x&quot; : 3 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee957&quot;), &quot;x&quot; : 4, &quot;j&quot; : 1 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee958&quot;), &quot;x&quot; : 4, &quot;j&quot; : 2 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee959&quot;), &quot;x&quot; : 4, &quot;j&quot; : 3 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee95a&quot;), &quot;x&quot; : 4, &quot;j&quot; : 4 } … { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee963&quot;), &quot;x&quot; : 4, &quot;j&quot; : 13 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee964&quot;), &quot;x&quot; : 4, &quot;j&quot; : 14 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee965&quot;), &quot;x&quot; : 4, &quot;j&quot; : 15 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee966&quot;), &quot;x&quot; : 4, &quot;j&quot; : 16 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee967&quot;), &quot;x&quot; : 4, &quot;j&quot; : 17 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee968&quot;), &quot;x&quot; : 4, &quot;j&quot; : 18 } has more
  13. 13. O Comando “it” (iterador) … { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee967&quot;), &quot;x&quot; : 4, &quot;j&quot; : 17 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee968&quot;), &quot;x&quot; : 4, &quot;j&quot; : 18 } has more > it { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee969&quot;), &quot;x&quot; : 4, &quot;j&quot; : 19 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee96a&quot;), &quot;x&quot; : 4, &quot;j&quot; : 20 }
  14. 14. Acessando dados a partir de uma Query (objeto “cursor”) > var cur = db.things.find() > while (cur.hasNext()) printjson(cur.next()); { &quot;_id&quot; : ObjectId(&quot;4e47fae21373c8f77f7ee955&quot;), &quot;name&quot; : &quot;mongo&quot; } { &quot;_id&quot; : ObjectId(&quot;4e47faeb1373c8f77f7ee956&quot;), &quot;x&quot; : 3 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee957&quot;), &quot;x&quot; : 4, &quot;j&quot; : 1 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee958&quot;), &quot;x&quot; : 4, &quot;j&quot; : 2 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee959&quot;), &quot;x&quot; : 4, &quot;j&quot; : 3 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee95a&quot;), &quot;x&quot; : 4, &quot;j&quot; : 4 } … { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee965&quot;), &quot;x&quot; : 4, &quot;j&quot; : 15 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee966&quot;), &quot;x&quot; : 4, &quot;j&quot; : 16 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee967&quot;), &quot;x&quot; : 4, &quot;j&quot; : 17 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee968&quot;), &quot;x&quot; : 4, &quot;j&quot; : 18 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee969&quot;), &quot;x&quot; : 4, &quot;j&quot; : 19 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee96a&quot;), &quot;x&quot; : 4, &quot;j&quot; : 20 }
  15. 15. forEach() ao invés de while() > db.things.find().forEach(printjson); { &quot;_id&quot; : ObjectId(&quot;4e47fae21373c8f77f7ee955&quot;), &quot;name&quot; : &quot;mongo&quot; } { &quot;_id&quot; : ObjectId(&quot;4e47faeb1373c8f77f7ee956&quot;), &quot;x&quot; : 3 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee957&quot;), &quot;x&quot; : 4, &quot;j&quot; : 1 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee958&quot;), &quot;x&quot; : 4, &quot;j&quot; : 2 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee959&quot;), &quot;x&quot; : 4, &quot;j&quot; : 3 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee95a&quot;), &quot;x&quot; : 4, &quot;j&quot; : 4 } … { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee965&quot;), &quot;x&quot; : 4, &quot;j&quot; : 15 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee966&quot;), &quot;x&quot; : 4, &quot;j&quot; : 16 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee967&quot;), &quot;x&quot; : 4, &quot;j&quot; : 17 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee968&quot;), &quot;x&quot; : 4, &quot;j&quot; : 18 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee969&quot;), &quot;x&quot; : 4, &quot;j&quot; : 19 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee96a&quot;), &quot;x&quot; : 4, &quot;j&quot; : 20 }
  16. 16. Tratando cursor no estilo array <ul><li>Nota: documentos até o mais alto acessado(quinto documento, no nosso caso) são todos carregados em RAM ao mesmo tempo </li></ul><ul><ul><li>Não apropriado para grandes coleções </li></ul></ul>> var cur = db.things.find(); > printjson(cur[4]); { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee959&quot;), &quot;x&quot; : 4, &quot;j&quot; : 3 }
  17. 17. Convertendo cursor em array <ul><li>Nota: cursores não são fotografias “ instantâneas ” </li></ul><ul><li>Operações feitas na coleção por usuários distintos concorrentemente podem ou não serem retornadas pelo cursor </li></ul><ul><li>Deve-se usar bloqueios para consultas instantâneas </li></ul>> var arr = db.things.find().toArray(); > arr[5]; { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee95a&quot;), &quot;x&quot; : 4, &quot;j&quot; : 4 }
  18. 18. Especificando retorno de Queries <ul><li>Query documents: </li></ul><ul><li>{a:A, b:B, …} significa “WHERE a==A AND b=BB AND …” </li></ul>> db.things.find( {name:&quot;mongo&quot;} ).forEach(printjson); { &quot;_id&quot; : ObjectId(&quot;4e47fae21373c8f77f7ee955&quot;), &quot;name&quot; : &quot;mongo&quot; }
  19. 19. Especificando retorno de Queries > db.things.find( {x:4} ).forEach(printjson); { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee957&quot;), &quot;x&quot; : 4, &quot;j&quot; : 1 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee958&quot;), &quot;x&quot; : 4, &quot;j&quot; : 2 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee959&quot;), &quot;x&quot; : 4, &quot;j&quot; : 3 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee95a&quot;), &quot;x&quot; : 4, &quot;j&quot; : 4 } … { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee965&quot;), &quot;x&quot; : 4, &quot;j&quot; : 15 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee966&quot;), &quot;x&quot; : 4, &quot;j&quot; : 16 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee967&quot;), &quot;x&quot; : 4, &quot;j&quot; : 17 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee968&quot;), &quot;x&quot; : 4, &quot;j&quot; : 18 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee969&quot;), &quot;x&quot; : 4, &quot;j&quot; : 19 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee96a&quot;), &quot;x&quot; : 4, &quot;j&quot; : 20 }
  20. 20. Especificando retorno de Queries > db.things.find( {x:4} , {j:true} ).forEach(printjson); { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee957&quot;), &quot;j&quot; : 1 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee958&quot;), &quot;j&quot; : 2 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee959&quot;), &quot;j&quot; : 3 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee95a&quot;), &quot;j&quot; : 4 } … { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee965&quot;), &quot;j&quot; : 15 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee966&quot;), &quot;j&quot; : 16 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee967&quot;), &quot;j&quot; : 17 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee968&quot;), &quot;j&quot; : 18 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee969&quot;), &quot;j&quot; : 19 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee96a&quot;), &quot;j&quot; : 20 } Partial Documents
  21. 21. findOne( ) – Syntactic Sugar <ul><li>Documentos podem ser obtidos </li></ul><ul><ul><li>invocando-se next() sobre um cursor </li></ul></ul><ul><ul><li>Tratando o cursor como um array </li></ul></ul><ul><ul><li>Convertendo cursor em array etc </li></ul></ul><ul><ul><li>findOne() : Açúcar Sintático </li></ul></ul>> printjson(db.things. findOne({j:4}) ); { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee95a&quot;), &quot;x&quot; : 4, &quot;j&quot; : 4 }
  22. 22. limit( ): limitando o retorno > db.things.find(). limit(3) ; { &quot;_id&quot; : ObjectId(&quot;4e47fae21373c8f77f7ee955&quot;), &quot;name&quot; : &quot;mongo&quot; } { &quot;_id&quot; : ObjectId(&quot;4e47faeb1373c8f77f7ee956&quot;), &quot;x&quot; : 3 } { &quot;_id&quot; : ObjectId(&quot;4e47fcb41373c8f77f7ee957&quot;), &quot;x&quot; : 4, &quot;j&quot; : 1 }
  23. 23. Sintaxe
  24. 24. Sintaxe
  25. 25. Sintaxe
  26. 26. Sintaxe
  27. 27. Sintaxe
  28. 28. MongoDB Ruby Driver <ul><li>Escrito em Ruby </li></ul><ul><li>Com uma extensão em C para velocidade </li></ul><ul><li>Otimizado à simplicidade </li></ul><ul><li>Pode ser usado sozinho, além servir de base para várias bibliotecas de mapeamento de objetos </li></ul>
  29. 29. Instalação <ul><li>Para garantir a última versão do rubygems </li></ul><ul><li>Para instalar a gem do mongo </li></ul><ul><li>Para otimização de performance, instala-se também a gem bson_ext </li></ul>$ gem update --system $ gem install mongo $ gem install bson_ext
  30. 30. Iniciando… <ul><li>Usando a gem </li></ul><ul><li>Criando uma conexão </li></ul>require 'rubygems' # not necessary for Ruby 1.9 require 'mongo' db = Mongo::Connection.new.db(&quot;mydb&quot;) db = Mongo::Connection.new(&quot;localhost&quot;).db(&quot;mydb&quot;) db = Mongo::Connection.new(&quot;localhost&quot;, 27017).db(&quot;mydb”)
  31. 31. Iniciando… <ul><li>Listando todas as bases </li></ul><ul><li>Removendo uma base </li></ul>connection = Mongo::Connection.new # (optional host/port args) connection.database_names.each { |name| puts name } connection.database_info.each { |info| puts info.inspect} connection.drop_database('database_name’)
  32. 32. Iniciando <ul><li>Listagem de coleções </li></ul><ul><li>Acessando uma coleção </li></ul><ul><li>Que é um alias para o método [ ] </li></ul>db.collection_names.each { |name| puts name } coll = db.collection(&quot;topicos&quot;) coll = db[”topicos&quot;]
  33. 33. Inserção de documentos { &quot;name&quot; : &quot;MongoDB&quot;, &quot;type&quot; : &quot;database&quot;, &quot;faculdade&quot; : &quot;Fecomp&quot; &quot;count&quot; : 1, &quot;info&quot; : { x : 203, y : 102 } } doc = {&quot;name&quot; => &quot;MongoDB&quot;, &quot;type&quot; => &quot;database&quot;, &quot;count&quot; => 1, &quot;faculdade&quot; => &quot;FECOMP&quot;, &quot;info&quot; => {&quot;x&quot; => 203, &quot;y&quot; => 102} } coll.insert(doc)
  34. 34. Atualização de documentos <ul><li>Reescrevendo o documento </li></ul><ul><li>Usando um operador atômico para mudar um valor único </li></ul><ul><li>asaa </li></ul>coll.update({&quot;_id&quot; => doc[:_id]}, {&quot;$set&quot; => {&quot;name&quot; => &quot;MongoDB Ruby&quot;}}) doc[&quot;name&quot;] = &quot;MongoDB Ruby&quot; coll.update({&quot;_id&quot; => doc[:_id]}, doc)
  35. 35. Busca <ul><li>Encontrando o primeiro documento </li></ul><ul><li>asaa </li></ul>=> {&quot;_id&quot;=>BSON::ObjectId('4e78d41bed686f02d1000001'), &quot;name&quot;=>&quot;MongoDB&quot;, &quot;faculdade&quot; : &quot;Fecomp”, &quot;info&quot;=>{&quot;x&quot;=>203, &quot;y&quot;=>102}, &quot;count&quot;=>1, &quot;type&quot;=>&quot;database”} my_doc = coll.find_one() puts my_doc.inspect
  36. 36. Adicionando mais documentos <ul><li>Contando documentos </li></ul>{ &quot;i&quot; : value } 100.times { |i| coll.insert(&quot;i&quot; => i) } puts coll.count()
  37. 37. Busca <ul><li>Usando um Cursor para obter todos os documentos </li></ul><ul><li>asaa </li></ul>coll.find().each { |row| puts row.inspect }
  38. 38. Busca com Queries <ul><li>Obtendo um único documento com queries </li></ul><ul><li>Obtendo um conjunto de documentos </li></ul><ul><li>asaa </li></ul>coll.find(&quot;i&quot; => 71).each { |row| puts row.inspect } coll.find(&quot;i&quot; => {&quot;$gt&quot; => 50}).each { |row| puts row.inspect } coll.find(&quot;i&quot; => {&quot;$gt&quot; => 20, &quot;$lte&quot; => 30}).each { |row| puts row.inspect }
  39. 39. Busca com Queries <ul><li>Queries com Expressões Regulares </li></ul><ul><li>Dinamicamente </li></ul><ul><li>asaa </li></ul>coll.find(&quot;name&quot; => /^M/).each { |row| puts row.inspect } search_string = params['search'] #Constructor Syntax coll.find({&quot;name&quot; => Regexp.new(search_string)}) # Literal syntax coll.find({&quot;name&quot; => /#{search_string}/})
  40. 40. Índices <ul><li>Criando índices </li></ul><ul><li>Explicit ”descending&quot; </li></ul><ul><li>asaa </li></ul>coll.create_index(&quot;i&quot;) coll.create_index([[&quot;i&quot;, Mongo::DESCENDING]])
  41. 41. Índices <ul><li>Criando índice geo-espacial </li></ul><ul><li>Query com limites </li></ul><ul><li>Obtendo a lista de índices de uma coleção </li></ul>people.create_index([[&quot;loc&quot;, Mongo::GEO2D]]) people.find({&quot;loc&quot; => {&quot;$near&quot; => [50, 50]}}, {:limit => 20}).each do |p| puts p.inspect end coll.index_information()
  42. 42. Mongoid <ul><li>Object-Document-Mapper (ODM) para MongoDB </li></ul><ul><li>Escrito em Ruby </li></ul><ul><li>Provém uma API familiar aos desenvolvedores Ruby acostumados com Active Record, enquanto alavanca o poder da ausência de schema do MongoDB </li></ul>
  43. 43. Instalação <ul><li>Para instalar a gem do mongoid </li></ul><ul><li>Arquivo de configuração mongoid.yml </li></ul><ul><li>Por programação </li></ul>$ gem install mongoid host: localhost database: mydb Mongoid.load!(&quot;path/to/your/mongoid.yml&quot;) Mongoid.configure do |config| config.master = Mongo::Connection.new.db(”mydb&quot;) end
  44. 44. Documentos <ul><li>Objetos devem incluir Mongoid::Document a fim de serem persistidos </li></ul><ul><li>Armazenamento </li></ul>class Person include Mongoid::Document end class Person include Mongoid::Document store_in :citizens end
  45. 45. Campos <ul><li>Outros tipos: Array, BigDecimal, Boolean, Date, DateTime, Float, Hash, Integer, Range, Symbol e Time </li></ul>class Person include Mongoid::Document store_in :citizens field :first_name, type: String field :middle_name, type: String field :last_name, type: String end
  46. 46. Campos: get e set <ul><li>Obtém o valor do campo first_name </li></ul><ul><li>Atribui o valor para o campo first_name </li></ul>person.first_name person[:first_name] person.read_attribute(:first_name) person.first_name = ”José&quot; person[:first_name] = ”José&quot; person.write_attribute(:first_name, ”José&quot;)
  47. 47. Campos: get e set para vários campos <ul><li>Obtém os valores dos campos em um hash </li></ul><ul><li>Atribui os valores de campos em um documento </li></ul>person.attributes Person.new(first_name: &quot;Jean-Baptiste&quot;, middle_name: &quot;Emmanuel&quot;) person.attributes = { first_name: &quot;Jean-Baptiste&quot;, middle_name: &quot;Emmanuel&quot; } person.write_attributes( first_name: &quot;Jean-Baptiste&quot;, middle_name: &quot;Emmanuel&quot; )
  48. 48. Defaults class Person include Mongoid::Document field :blood_alcohol_level, type: Float, default: 0.40 field :last_drink, type: Time, default: -> { 10.minutes.ago } end
  49. 49. Serialização de Campos customizados class Profile include Mongoid::Document field :location, type: Point end class Point include Mongoid::Fields::Serializable def deserialize(object) [ object[&quot;x&quot;], object[&quot;y&quot;] ] end def serialize(object) { &quot;x&quot; => object[0], &quot;y&quot; => object[1] } end end
  50. 50. Campos Dinâmicos <ul><li>Suporte a Campos dinâmicos </li></ul><ul><ul><li>Permite get, set e persistência de atributos mesmo que um campo não tenha sido definido para ele </li></ul></ul><ul><ul><li>Não usar getters e setters </li></ul></ul><ul><ul><li>Usar os métodos acessores: </li></ul></ul>person[:gender] person.read_attribute(:gender) person[:gender] = &quot;Male&quot; person.write_attribute(:gender, &quot;Male&quot;)
  51. 51. Acesso: Protected class User include Mongoid::Document field :first_name, type: String field :password, type: String attr_protected :password end # Ajusta atributos em uma pessoa de forma apropriada Person.new(first_name: &quot;Corbin&quot;) person.attributes = { first_name: &quot;Corbin&quot; } person.write_attributes(first_name: &quot;Corbin&quot;) # Tenta ajudar os valores, levantando um erro Person.new(first_name: &quot;Corbin&quot;, password: &quot;password&quot;) person.attributes = { first_name: &quot;Corbin&quot;, password: &quot;password&quot; } person.write_attributes(first_name: &quot;Corbin&quot;, password: &quot;password&quot;)
  52. 52. Acesso: Accessible class User include Mongoid::Document field :first_name, type: String field :password, type: String attr_accessible :first_name end # Ajusta atributos em uma pessoa de forma apropriada Person.new(first_name: &quot;Corbin&quot;) person.attributes = { first_name: &quot;Corbin&quot; } person.write_attributes(first_name: &quot;Corbin&quot;) # Tenta ajudar os valores, levantando um erro Person.new(first_name: &quot;Corbin&quot;, password: &quot;password&quot;) person.attributes = { first_name: &quot;Corbin&quot;, password: &quot;password&quot; } person.write_attributes(first_name: &quot;Corbin&quot;, password: &quot;password&quot;)
  53. 53. Acesso: Overriding Person.new(first_name: &quot;Corbin&quot;) do |person| person.password = &quot;password&quot; end
  54. 54. Dirty Tracking person = Person.first person.name = &quot;Alan Garner” # Checa para ver se o documento foi alterado person.changed? #=> true # Obtém um array dos nomes dos campos alterados person.changed #=> [ :name ] # Obtém um hash do antigo e do novo valor para cada campo person.changes #=> { &quot;name&quot; => [ &quot;Alan Parsons&quot;, &quot;Alan Garner&quot; ] } # Checa se um campo específico foi alterado person.name_changed? #=> true # Obtém as mudanças para um campo específico person.name_change #=> [ &quot;Alan Parsons&quot;, &quot;Alan Garner&quot; ] # Obtém o valor anterior de um campo person.name_was #=> &quot;Alan Parsons&quot; class Person include Mongoid::Document field :name, type: String end
  55. 55. Limpando mudanças person = Person.first person.name = &quot;Alan Garner&quot; # Reinicializa o nome alterado de volta ao original person.reset_name! person.name #=> &quot;Alan Parsons&quot;
  56. 56. Vendo as mudanças anteriores person = Person.first person.name = &quot;Alan Garner&quot; person.save #=> Clears out current changes. # Vê mudanças anteriores person.previous_changes #=> { &quot;name&quot; => [ &quot;Alan Parsons&quot;, &quot;Alan Garner&quot; ] }
  57. 57. Herança class Canvas include Mongoid::Document field :name, type: String embeds_many :shapes end class Browser < Canvas field :version, type: Integer scope :recent, where(:version.gt => 3) end class Firefox < Browser end
  58. 58. Herança class Shape include Mongoid::Document field :x, type: Integer field :y, type: Integer embedded_in :canvas end class Circle < Shape field :radius, type: Float end class Rectangle < Shape field :width, type: Float field :height, type: Float end
  59. 59. Persistência <ul><li>Model.create </li></ul><ul><li>Model.create! </li></ul><ul><li>Model#save </li></ul><ul><li>Model#save! </li></ul><ul><li>Model#update_attributes </li></ul><ul><li>Model#update_attributes! </li></ul><ul><li>Model#update_attribute </li></ul><ul><li>Model#delete </li></ul><ul><li>Model#destroy </li></ul><ul><li>Model.delete_all </li></ul><ul><li>Model.destroy_all </li></ul>
  60. 60. Model.create # Insere um novo poeta na base. Person.create(first_name: &quot;Heinrich&quot;, last_name: &quot;Heine&quot;) # Isto também pode ser feito usando um bloco Person.create(first_name: &quot;Heinrich&quot;) do |doc| doc.last_name = &quot;Heine&quot; end collections[”citizens&quot;].insert({ &quot;_id&quot; : ..., &quot;first_name&quot; : &quot;Heinrich&quot;, &quot;last_name&quot; : &quot;Heine” })
  61. 61. Model.create! # Insere um novo poeta na base, levantando um erro # se a validação falhar. Person.create!(first_name: &quot;Heinrich&quot;, last_name: &quot;Heine&quot;) # Isto também pode ser feito usando um bloco Person.create!(first_name: &quot;Heinrich&quot;) do |doc| doc.last_name = &quot;Heine&quot; end collections[”citizens&quot;].insert({ &quot;_id&quot; : ..., &quot;first_name&quot; : &quot;Heinrich&quot;, &quot;last_name&quot; : &quot;Heine” })
  62. 62. Model#save # Insere um novo poeta na base. person = Person.new(first_name: &quot;Heinrich&quot;, last_name: &quot;Heine&quot;) person.save # Grava sem executar as validações person.save(validate: false) # Grava os campos modificados de um documento existente person.first_name = &quot;Christian Johan&quot; person.save # Comando de inserção de um novo documento collections[”sitizens&quot;].insert({ &quot;_id&quot; : ..., &quot;first_name&quot; : &quot;Heinrich&quot;, &quot;last_name&quot; : &quot;Heine” }) # Comando de atualização do doc modificado collections[&quot;people&quot;].update({ { &quot;_id&quot; : ... }, { &quot;$set&quot; : { &quot;first_name&quot; : &quot;Christian Johan” } } })
  63. 63. Model#save! # Insere um novo poeta na base. person = Person.new(first_name: &quot;Heinrich&quot;, last_name: &quot;Heine&quot;) person.save! # Grava os campos modificados de um documento existente person.first_name = &quot;Christian Johan&quot; person.save! # Comando de inserção de um novo documento collections[”sitizens&quot;].insert({ &quot;_id&quot; : ..., &quot;first_name&quot; : &quot;Heinrich&quot;, &quot;last_name&quot; : &quot;Heine” }) # Comando de atualização do doc modificado collections[&quot;people&quot;].update({ { &quot;_id&quot; : ... }, { &quot;$set&quot; : { &quot;first_name&quot; : &quot;Christian Johan” } } })
  64. 64. Model#update_attributes # Update the provided attributes. person.update_attributes(first_name: &quot;Jean&quot;, last_name: &quot;Zorg&quot;) # Comando de atualização do doc modificado collections[”citizens&quot;].update({ &quot;_id&quot; : ..., &quot;first_name&quot; : ”Jean&quot;, &quot;last_name&quot; : ”Zorg” })
  65. 65. Model#update_attributes! # Update the provided attributes. person.update_attributes!(first_name: &quot;Jean&quot;, last_name: &quot;Zorg&quot;) # Comando de atualização do doc modificado collections[”citizens&quot;].update({ &quot;_id&quot; : ..., &quot;first_name&quot; : ”Jean&quot;, &quot;last_name&quot; : ”Zorg” })
  66. 66. Model#update_attribute # Update the provided attributes. person.update_attribute(first_name: &quot;Jean&quot;) # Comando de atualização do doc modificado collections[”citizens&quot;].update({ &quot;_id&quot; : ..., &quot;first_name&quot; : ”Jean” })
  67. 67. Model#delete person.delete collections[”citizens&quot;].remove(&quot;_id&quot; : ... )
  68. 68. Model#destroy person.destroy collections[”citizens&quot;].remove(&quot;_id&quot; : ... )
  69. 69. Model#delete_all # Apaga todos os documentos da coleção Person.delete_all # Apaga todos os documentos da coleção que satisfaçam a condição Person.delete_all(conditions: { first_name: &quot;Heinrich&quot; }) # Comando para apagar todos collections[”citizens&quot;].remove # Comando para apagar docs que satisfaçam condição collections[”citizens&quot;].remove(&quot;first_name&quot; : &quot;Heinrich&quot;)
  70. 70. Model#destroy_all # Apaga todos os documentos da coleção Person.destroy_all # Apaga todos os documentos da coleção que satisfaçam a condição Person.destroy_all(conditions: { first_name: &quot;Heinrich&quot; }) # Comando para apagar todos collections[”citizens&quot;].remove # Comando para apagar docs que satisfaçam condição collections[”citizens&quot;].remove(&quot;first_name&quot; : &quot;Heinrich&quot;)
  71. 71. Atomicidade na Persistênicia <ul><li>Embora Mongoid realize operações atômicas por trás da cena por default, há casos em que se deseja fazê-lo explicitamente sem persistir outros campos </li></ul><ul><ul><li>Model#add_to_set </li></ul></ul><ul><ul><li>Model#inc </li></ul></ul><ul><ul><li>Model#pull_all </li></ul></ul><ul><ul><li>Model#push </li></ul></ul>
  72. 72. Model#add_to_set person.add_to_set(:aliases, &quot;Bond&quot;) collections[”citizens&quot;].update( { &quot;_id&quot; : ... }, { &quot;$addToSet&quot; : { &quot;aliases&quot; : &quot;Bond&quot; } } )
  73. 73. Model#inc person.inc(:age, 1) collections[”citizens&quot;].update( { &quot;_id&quot; : ... }, { &quot;$inc&quot; : { &quot;age&quot; : 1 } } )
  74. 74. Model#pull_all person.pull_all(:aliases, [ &quot;Bond&quot;, &quot;James&quot; ]) collections[”citizens&quot;].update( { &quot;_id&quot; : ... }, { &quot;$pullAll&quot; : { &quot;aliases&quot; : [ &quot;Bond&quot;, &quot;James&quot; ] } } )
  75. 75. Model#push person.push(:aliases, &quot;007&quot;) collections[”citizens&quot;].update( { &quot;_id&quot; : ... }, { &quot;$push&quot; : { &quot;aliases&quot; : &quot;007&quot; } } )
  76. 76. Querying <ul><li>Mongoid queries são em Criteria, um wrapper de queries dinâmicas do MongoDB, que é encadeável e de avaliação “tardia”, por só acessar a base quando necessário. </li></ul>
  77. 77. Criteria – métodos de query <ul><li>Model.all_in </li></ul><ul><li>Model.also_in </li></ul><ul><li>Criteria#and </li></ul><ul><li>Model.any_in </li></ul><ul><li>Model.any_of </li></ul><ul><li>Model.asc </li></ul><ul><li>Model.desc </li></ul><ul><li>Criteria#distinct </li></ul><ul><li>Model.excludes </li></ul><ul><li>Model.includes </li></ul><ul><li>Model.limit </li></ul><ul><li>Model.near </li></ul><ul><li>Model.not_in </li></ul><ul><li>Model.only </li></ul><ul><li>Model.order_by </li></ul><ul><li>Model.skip </li></ul><ul><li>Model.where </li></ul><ul><li>Model.without </li></ul>
  78. 78. Model.all_in | Criteria#all_in # Traz todas as pessoas que tem Bond e 007 como aliases Person.all_in(aliases: [ &quot;Bond&quot;, &quot;007&quot; ]) { &quot;aliases&quot; : { &quot;$all&quot; : [ &quot;Bond&quot;, &quot;007&quot; ] }}
  79. 79. Model.also_in | Criteria#also_in # Traz pessoas com aliases igual a Bond ou 007 Person.also_in(aliases: [ &quot;Bond&quot;, &quot;007&quot; ]) Person.any_in(aliases: [ &quot;Bond&quot; ]).also_in(aliases: [ &quot;007&quot; ]) { &quot;aliases&quot; : { &quot;$in&quot; : [ &quot;Bond&quot;, &quot;007&quot; ] }}
  80. 80. Criteria#and # Traz todas as pessoas com last_name Jordan e first_name iniciando com d Person.where(last_name: &quot;Jordan&quot;).and(first_name: /^d/i) { &quot;last_name&quot; : &quot;Jordan&quot;, &quot;first_name&quot; : /^d/i }
  81. 81. Model.any_in | Criteria#any_in # Traz todas as pessoas com Bond e/ou 007 como aliases Person.any_in(aliases: [ &quot;Bond&quot;, &quot;007&quot; ]) Person. any_in(aliases: [ &quot;Bond&quot;, &quot;007&quot;, &quot;James&quot; ]). any_in(aliases: [ &quot;Bond&quot;, &quot;007&quot; ]) { &quot;aliases&quot; : { &quot;$in&quot; : [ &quot;Bond&quot;, &quot;007&quot; ] }}
  82. 82. Model.any_of | Criteria#any_of # Traz todas as pessoas com last_name Penn ou Teller Person.any_of({ last_name: &quot;Penn&quot; }, { last_name: &quot;Teller&quot; }) { &quot;last_name&quot; : { &quot;$or&quot; : [ { &quot;last_name&quot; : &quot;Penn&quot; }, { &quot;last_name&quot; : &quot;Teller&quot; } ] } }
  83. 83. Model.asc | Criteria#asc # Retorna pessoas ordenadas por first_name e last_name em ordem alfabética crescente Person.asc(:first_name, :last_name) Person.ascending(:first_name, :last_name) { &quot;sort&quot; : {[ [ &quot;first_name&quot;, Mongo::ASCENDING ], [ &quot;last_name&quot;, Mongo::ASCENDING ] ]} }
  84. 84. Model.where | Criteria#where # Traz todas as pessocas com first_name Emmanuel Person.where(first_name: &quot;Emmanuel&quot;) # Traz todas as pessoas com first_name Emmanuel usando Javascript. Person.where(&quot;this.first_name == 'Emmanuel'&quot;) # Traz todas as pessoas de Berlin, onde address é “embutido” Person.where(&quot;addresses.city&quot; => &quot;Berlin&quot;) { &quot;first_name&quot; : &quot;Emmanuel&quot; } { &quot;$where&quot; : &quot;this.first_name == 'Emmanuel'&quot; } { &quot;addresses.city&quot; : &quot;Berlin&quot; }
  85. 85. Model.where | Criteria#where # Exemplo de queries usando símbolo h4s para realizar critérios mais complexos Person.where(:title.all => [&quot;Sir&quot;]) Person.where(:age.exists => true) Person.where(:age.gt => 18) Person.where(:age.gte => 18) Person.where(:title.in => [&quot;Sir&quot;, &quot;Madam&quot;]) Person.where(:age.lt => 55) Person.where(:age.lte => 55) Person.where(:title.ne => &quot;Mr&quot;) Person.where(:title.nin => [&quot;Esquire&quot;]) Person.where(:aliases.size => 2) Person.where(:location.near => [ 22.50, -21.33 ]) Person.where(:location.within => { &quot;$center&quot; => [ [ 50, -40 ], 1 ] })
  86. 86. Criteria + Modificação <ul><li>Pode-se usar Mongoid criteria para se criar um seletor e usá-lo para se modificar documentos no banco </li></ul>
  87. 87. Criação # Cria uma pessoa com title Sir e first_name Lancelot e a persiste Person.where(title: &quot;Sir&quot;, first_name: &quot;Lancelot&quot;).create Person.where(title: &quot;Sir&quot;).create(first_name: &quot;Lancelot&quot;) # Constrói uma pessoa com title Sir e first_name Lancelot, sem salvá-la Person.where(title: &quot;Sir&quot;, first_name: &quot;Lancelot&quot;).build Person.where(title: &quot;Sir&quot;).build(first_name: &quot;Lancelot&quot;)
  88. 88. Atualização # Atualiza todas as pessoas que têm last_name Oldman com um novo first_name Person.where(last_name: &quot;Oldman&quot;).update_all( first_name: &quot;Pappa Gary&quot; )
  89. 89. Remoção # Apaga todos os cavaleiros de Sir Arthur da base Person.where(title: &quot;Sir&quot;).and(king: &quot;Arthur&quot;).delete_all Person.where(title: &quot;Sir&quot;, king: &quot;Arthur&quot;).destroy_all
  90. 90. Finders <ul><li>Métodos Finders não são encadeáveis </li></ul><ul><li>Retornam arrays de documentos ou um documento único (com exceções) </li></ul><ul><li>Métodos: </li></ul><ul><ul><li>Model.all </li></ul></ul><ul><ul><li>Model.count </li></ul></ul><ul><ul><li>Model.exists? </li></ul></ul><ul><ul><li>Model.find </li></ul></ul><ul><ul><li>Model.find_or_create_by </li></ul></ul><ul><ul><li>Model.find_or_initialize_by </li></ul></ul><ul><ul><li>Model.first </li></ul></ul><ul><ul><li>Model.last </li></ul></ul>
  91. 91. Model.all # Encontra todas as pessoas pelas condições e opções compatíveis com MongoDB Person.all Person.all(conditions: { first_name: /^dur/i, &quot;addresses.city&quot; => &quot;Berlin&quot; }) Person.all(conditions: { title: &quot;Sir&quot; }, limit: 5) Person.all(sort: [[ :first_name, :asc ]])
  92. 92. Model.count # Obtém o montante de documentos que satisfazem a(s) condição(ões) Person.count Person.count(conditions: { title: &quot;Sir&quot; })
  93. 93. Model.exists? # Existe algum documento na base que satisfaça a(s) condição(ões)? Person.exists? Person.exists?(conditions: { title: &quot;Sir&quot; })
  94. 94. Model.find | Criteria#find #Permite encontrar um vários documentos pelo id Person.find(id) Person.find(&quot;4baa56f1230048567300485c&quot;) Person.where(last_name: &quot;Black&quot;).find(id) Person.find([id_one, id_two]) Person.find([&quot;4baa56f1230048567300485c&quot;,&quot;4baa56f1230048567300485d&quot;]) Person.where(last_name: &quot;Black&quot;).find([ id_one, id_two ])
  95. 95. Model.find_or_create_by # Encontra um documento que satisfaça a condição ou cria um novo, se não houver nada persistido Person.find_or_create_by(first_name: &quot;Syd&quot;, last_name: &quot;Vicious&quot;)
  96. 96. Model.find_or_initialize_by # Encontra um documento que satisfaça a condição ou inicializa um novo, se não houver nada persistido Person.find_or_initialize_by(first_name: &quot;Syd&quot;, last_name: &quot;Vicious&quot;)
  97. 97. Model.first # Encontra o primeiro documento da base que satisfaça a condição. Retorna um documento ou nil, se nada for encontrado. Pode-se definir a ordenação, a fim de se ditar qual documento deve ser retornado. Person.first(conditions: { first_name: &quot;Syd&quot; }) Person.first(sort: [[ :first_name, :asc ]])
  98. 98. Model.last # Encontra o último documento da base que satisfaça a condição. Retorna um documento ou nil, se nada for encontrado. Pode-se definir a ordenação, a fim de se ditar qual documento deve ser retornado. Person.last(conditions: { first_name: &quot;Syd&quot; }) Person.last(sort: [[ :first_name, :asc ]])
  99. 99. Escopos <ul><li>Mongoid permite definir escopos dentro dos modelos, a fim de se filtrar resultados de busca </li></ul><ul><li>São definidos no nível da Classe </li></ul><ul><li>São encadeáveis </li></ul>
  100. 100. Named Scopes class Person include Mongoid::Document field :occupation, type : String field :age, type : Integer scope :rock_n_rolla, where ( occupation : &quot;Rockstar&quot;) scope :washed_up, where (:age. gt => 30) scope :over, ->( limit ) { where (:age .gt => limit ) } end # Encontra todos os roqueiros Person.rock_n_rolla # Econtra os roqueiros que já deviam ter parado Person.washed_up.rock_n_rolla # Encontra o Tremendão Person.rock_n_rolla.over(60) scope :current, where(:start_date.lte => Date.today) scope :current, -> { where(:start_date.lte => Date.today) }
  101. 101. Métodos de Classe # Encontra todos os roqueiros Person.rock_n_rolla # Econtra os roqueiros que já deviam ter parado Person.washed_up.rock_n_rolla # Encontra o Tremendão Person.rock_n_rolla.over(60) class Person include Mongoid::Document field :occupation, type : String field :age, type : Integer class << self def rock_n_rolla where ( occupation : &quot;Rockstar&quot;) end def washed_up where (:age. gt => 30) end def over ( limit ) where (:age. gt => limit ) end end end
  102. 102. Métodos de Classe e Named Scopes Person.rock_n_rolla Person.washed_up.rock_n_rolla Person.rock_n_rolla.over(60) class Person include Mongoid::Document field :occupation, type : String field :age, type : Integer scope :washed_up, where (:age. gt => 30) scope :over, ->( limit ) { where (:age .gt => limit ) } class self. rock_n_rolla where ( occupation : &quot;Rockstar&quot;) end end
  103. 103. Default Scopes # Econtra os roqueiros que já deviam ter parado Person.washed_up # Se quiser encontrar os mais velhos que não são roqueiros Person.unscoped.washed_up class Person include Mongoid::Document field :occupation, type : String field :age, type : Integer default_scope where ( occupation : &quot;Rockstar&quot;) scope :washed_up, where (:age. gt => 30) end
  104. 104. Relacionamentos <ul><li>Associações entre modelos no domínio e no banco. </li></ul><ul><li>Podem ser “embutidas” ou “referenciadas </li></ul><ul><li>Embedded: </li></ul><ul><ul><li>1…N: “embeds_many” e “embedded_in” </li></ul></ul><ul><ul><li>1…1: “embeds_one” e “embedded_in” </li></ul></ul><ul><li>Referenced: </li></ul><ul><ul><li>1…N: “has_many” e “belongs_to” </li></ul></ul><ul><ul><li>1…1: “has_one” e “belongs_to” </li></ul></ul><ul><ul><li>N…N: “has_and_belongs_to_many” e “has_and_belongs_to_many” </li></ul></ul>
  105. 105. Callbacks <ul><li>after_initialize </li></ul><ul><li>before_validation </li></ul><ul><li>after_validation </li></ul><ul><li>before_create </li></ul><ul><li>around_create </li></ul><ul><li>after_create </li></ul><ul><li>before_update </li></ul><ul><li>around_update </li></ul><ul><li>after_update </li></ul><ul><li>before_save </li></ul><ul><li>around_save </li></ul><ul><li>after_save </li></ul><ul><li>before_destroy </li></ul><ul><li>around_destroy </li></ul><ul><li>after_destroy </li></ul>
  106. 106. Callbacks class Article include Mongoid::Document field :name, type: String set_callback(:save, :before) do |document| document.generate_slug end protected def generate_slug self.slug = name.to_permalink end end class Article include Mongoid::Document field :name, type: String field :body, type: String field :slug, type: String before_create :generate_slug protected def generate_slug self.slug = name.to_permalink end end
  107. 107. Observers <ul><li>Implementa o comportamento fora da classe </li></ul><ul><li>Instanciação </li></ul>class ArticleObserver < Mongoid::Observer def after_save(article) Notifications.article(&quot;admin@do.com&quot;, &quot;New article&quot;, article).deliver end end require 'article_observer' require 'audit_observer' Mongoid.observers = ArticleObserver, AuditObserver Mongoid.instantiate_observers config.mongoid.observers = :article_observer, :audit_observer Config/application.rb
  108. 108. Mapeamento class AuditObserver < Mongoid::Observer observe :account, :balance def after_update(record) AuditTrail.new(record, &quot;UPDATED&quot;) end end
  109. 109. Validations <ul><li>validates_acceptance_of </li></ul><ul><li>validates_associated </li></ul><ul><li>validates_confirmation_of </li></ul><ul><li>validates_exclusion_of </li></ul><ul><li>validates_format_of </li></ul><ul><li>validates_inclusion_of </li></ul><ul><li>validates_length_of </li></ul><ul><li>validates_numericality_of </li></ul><ul><li>validates_presence_of </li></ul><ul><li>validates_uniqueness_of </li></ul>
  110. 110. Fontes <ul><li>MongoDB: Features, Quickstart and Tutorial( http://www.mongdb.com ) </li></ul><ul><li>MongoDB Ruby Driver Tutorial ( http://api.mongodb.org/ruby/current/file.TUTORIAL.html ) </li></ul><ul><li>Mongoid (http://mongoid.org/) </li></ul>

×