O slideshow foi denunciado.
Seu SlideShare está sendo baixado. ×

Uma Breve Introdução ao MongoDB

Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Próximos SlideShares
MongoDB com a Turma do Chaves
MongoDB com a Turma do Chaves
Carregando em…3
×

Confira estes a seguir

1 de 110 Anúncio

Mais Conteúdo rRelacionado

Quem viu também gostou (20)

Semelhante a Uma Breve Introdução ao MongoDB (20)

Anúncio

Mais de Eduardo Nicola F. Zagari (11)

Mais recentes (20)

Anúncio

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>

×