zentradi 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/Gemfile +12 -0
- data/LICENSE +20 -0
- data/README.rdoc +98 -0
- data/Rakefile +63 -0
- data/VERSION +1 -0
- data/lib/zentradi.rb +13 -0
- data/lib/zentradi/class_helpers.rb +46 -0
- data/lib/zentradi/connection.rb +48 -0
- data/lib/zentradi/document.rb +83 -0
- data/lib/zentradi/identity_map.rb +75 -0
- data/lib/zentradi/instantiators.rb +36 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/zentradi/document_spec.rb +69 -0
- data/spec/zentradi/identity_map_spec.rb +26 -0
- data/spec/zentradi/indexes_spec.rb +26 -0
- data/spec/zentradi_spec.rb +7 -0
- metadata +157 -0
data/.document
ADDED
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Emmanuel Oga
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
= zentradi
|
2
|
+
|
3
|
+
Zentradi provides a [wannabe] minimalistic set of tools for managing the mongodb ruby driver.
|
4
|
+
|
5
|
+
For now this is basically my playground for experimenting with mongodb.
|
6
|
+
|
7
|
+
Developed mainly under ruby 1.9.1, using bundler for development mode dependencies management.
|
8
|
+
|
9
|
+
== Usage
|
10
|
+
|
11
|
+
The class just acts as a convenient way to group all the mongo artefacts:
|
12
|
+
|
13
|
+
Zentradi::Document.connection
|
14
|
+
Zentradi::Document.database
|
15
|
+
Zentradi::Document.collection
|
16
|
+
|
17
|
+
The Zentradi::Document.mongo method is a short cut for setting all those at the same time:
|
18
|
+
|
19
|
+
class Post < Zentradi::Document
|
20
|
+
mongo :database => "zentradi", :collection => "posts"
|
21
|
+
|
22
|
+
collection.create_index "key", true # Access the collection directly, set an index.
|
23
|
+
|
24
|
+
mongo_accessor :other_key
|
25
|
+
end
|
26
|
+
|
27
|
+
Some examples:
|
28
|
+
|
29
|
+
Post.create!(:some => :attributes)
|
30
|
+
|
31
|
+
Post.first.destroy
|
32
|
+
|
33
|
+
Post.first(:some => :attribute)
|
34
|
+
|
35
|
+
p = Post.new(some: "attributes")
|
36
|
+
p.some
|
37
|
+
p.document.some.other!.key = "hey!"
|
38
|
+
p.save
|
39
|
+
p.reload
|
40
|
+
|
41
|
+
etc...
|
42
|
+
|
43
|
+
I opted for explicit configuration of each document class. While using the
|
44
|
+
Class.inherited hook might sound cool, I'm still undecided about wetter adding
|
45
|
+
such magic is really worth the effort.
|
46
|
+
|
47
|
+
The Zentradi::Document#document method provide access to the "raw" mongo
|
48
|
+
document, which is an instance of Hashie::Mash object (instead of a Hash) for
|
49
|
+
convenience.
|
50
|
+
|
51
|
+
The mongo_accessor class method is a shortcut to access the keys of the
|
52
|
+
document (Mash) from an instance of Document, but that is not really necessary.
|
53
|
+
|
54
|
+
=== BUT WHY?!
|
55
|
+
|
56
|
+
In brief, the [pretentious? :p] philosophy of this project is "less code is
|
57
|
+
better code".
|
58
|
+
|
59
|
+
In particular, I want:
|
60
|
+
|
61
|
+
[
|
62
|
+
"magic",
|
63
|
+
"ruby hooks overrides",
|
64
|
+
"additions to the mongo mapper API",
|
65
|
+
"plugins paraphernalia",
|
66
|
+
"use and abuse of generated methods -- find_by_blah_blah anyone? -- ",
|
67
|
+
"features of ActiveRecord, Datamapper, [INSERT ORM HERE]"
|
68
|
+
].map do |bad_thing|
|
69
|
+
"As little #{ bad_thing } as possible"
|
70
|
+
end
|
71
|
+
|
72
|
+
=== How about validations, callbacks, state machines, carbonated time bomb mirror device?
|
73
|
+
|
74
|
+
I'm afraid you'll have to implement all those yourself if you need them. Or
|
75
|
+
better yet! grab some gems!
|
76
|
+
|
77
|
+
I haven't toyed yet with adding ActiveModel compatibility. Really, such thing
|
78
|
+
is a little out of this scope of this project, although sounds like a fun
|
79
|
+
thing to try on a rainy weekend :p.
|
80
|
+
|
81
|
+
=== DISCLAIMER
|
82
|
+
|
83
|
+
You might be interested to know, this is alpha quality software. I don't use it
|
84
|
+
myself for any production project yet. Standard disclaimers apply.
|
85
|
+
|
86
|
+
== Note on Patches/Pull Requests
|
87
|
+
|
88
|
+
* Fork the project.
|
89
|
+
* Make your feature addition or bug fix.
|
90
|
+
* Add tests for it. This is important so I don't break it in a
|
91
|
+
future version unintentionally.
|
92
|
+
* Commit, do not mess with rakefile, version, or history.
|
93
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
94
|
+
* Send me a pull request. Bonus points for topic branches.
|
95
|
+
|
96
|
+
== Copyright
|
97
|
+
|
98
|
+
Copyright (c) 2010 Emmanuel Oga. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
begin
|
2
|
+
# Try to require the preresolved locked set of gems.
|
3
|
+
require File.expand_path('.bundle/environment', __FILE__)
|
4
|
+
rescue LoadError
|
5
|
+
# Fall back on doing an unlocked resolve at runtime.
|
6
|
+
require "rubygems"
|
7
|
+
require "bundler"
|
8
|
+
Bundler.setup
|
9
|
+
end
|
10
|
+
Bundler.require
|
11
|
+
|
12
|
+
begin
|
13
|
+
require 'jeweler'
|
14
|
+
Jeweler::Tasks.new do |gem|
|
15
|
+
gem.name = "zentradi"
|
16
|
+
gem.summary = %Q{minimalistic tools for accessing mongodb}
|
17
|
+
gem.description = %Q{minimalistic tools for accessing mongodb}
|
18
|
+
gem.email = "EmmanuelOga@gmail.com"
|
19
|
+
gem.homepage = "http://github.com/EmmanuelOga/zentradi"
|
20
|
+
gem.authors = ["Emmanuel Oga"]
|
21
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
22
|
+
gem.add_development_dependency "rake"
|
23
|
+
gem.add_dependency "mongo"
|
24
|
+
gem.add_dependency "mongo_ext"
|
25
|
+
gem.add_dependency "weak_hash"
|
26
|
+
gem.add_dependency "hashie"
|
27
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
28
|
+
end
|
29
|
+
Jeweler::GemcutterTasks.new
|
30
|
+
rescue LoadError
|
31
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
32
|
+
end
|
33
|
+
|
34
|
+
$LOAD_PATH.unshift File.expand_path('lib')
|
35
|
+
|
36
|
+
require 'zentradi'
|
37
|
+
|
38
|
+
require 'spec/rake/spectask'
|
39
|
+
|
40
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
41
|
+
spec.libs << 'lib' << 'spec'
|
42
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
43
|
+
end
|
44
|
+
|
45
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
46
|
+
spec.libs << 'lib' << 'spec'
|
47
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
48
|
+
spec.rcov = true
|
49
|
+
end
|
50
|
+
|
51
|
+
task :spec => :check_dependencies
|
52
|
+
|
53
|
+
task :default => :spec
|
54
|
+
|
55
|
+
require 'rake/rdoctask'
|
56
|
+
Rake::RDocTask.new do |rdoc|
|
57
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
58
|
+
|
59
|
+
rdoc.rdoc_dir = 'rdoc'
|
60
|
+
rdoc.title = "zentradi #{version}"
|
61
|
+
rdoc.rdoc_files.include('README*')
|
62
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
63
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
data/lib/zentradi.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
require 'weak_hash'
|
3
|
+
require 'mongo'
|
4
|
+
|
5
|
+
module Zentradi
|
6
|
+
autoload :Utils, "zentradi/utils"
|
7
|
+
autoload :ClassHelpers, 'zentradi/class_helpers'
|
8
|
+
autoload :Instantiators, 'zentradi/instantiators'
|
9
|
+
autoload :IdentityMap, 'zentradi/identity_map'
|
10
|
+
autoload :Connection, 'zentradi/connection'
|
11
|
+
autoload :Finders, 'zentradi/finders'
|
12
|
+
autoload :Document, 'zentradi/document'
|
13
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Zentradi
|
2
|
+
# Some random helpers to be used at class level.
|
3
|
+
module ClassHelpers
|
4
|
+
|
5
|
+
def instance_access_to_class_methods(*names)
|
6
|
+
names.each do |name|
|
7
|
+
module_eval(<<-EOMETHOD, __FILE__, __LINE__ + 1)
|
8
|
+
def #{ name }(*args, &block)
|
9
|
+
self.class.#{ name }(*args, &block)
|
10
|
+
end
|
11
|
+
EOMETHOD
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# creates a shortcut for accessing keys
|
16
|
+
# on the mongo document.
|
17
|
+
# Not really needed but seems like after
|
18
|
+
# ActiveRecord nobody can live without this
|
19
|
+
# (including me? :-)
|
20
|
+
def mongo_accessor(*keys)
|
21
|
+
keys.each do |key|
|
22
|
+
module_eval(<<-EOMETHOD, __FILE__, __LINE__ + 1)
|
23
|
+
def #{ key }
|
24
|
+
document[#{key.inspect}]
|
25
|
+
end
|
26
|
+
|
27
|
+
def #{ key }=(val)
|
28
|
+
document[#{key.inspect}] = val
|
29
|
+
end
|
30
|
+
EOMETHOD
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def delegate(*methods)
|
35
|
+
to = methods.pop[:to]
|
36
|
+
methods.each do |name|
|
37
|
+
module_eval(<<-EOMETHOD, __FILE__, __LINE__ + 1)
|
38
|
+
def #{ name }(*args, &block)
|
39
|
+
#{to}.#{name}(*args, &block)
|
40
|
+
end
|
41
|
+
EOMETHOD
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Zentradi
|
2
|
+
# methods to manage the mongo driver communication artefacts
|
3
|
+
module Connection
|
4
|
+
|
5
|
+
def connection(*args)
|
6
|
+
@_connection = nil unless args.empty?
|
7
|
+
@_connection ||= Mongo::Connection.new(*args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def database(database_name = nil)
|
11
|
+
@_database = nil unless database_name.nil?
|
12
|
+
@_database ||= connection.db(database_name)
|
13
|
+
end
|
14
|
+
|
15
|
+
def collection(collection_name = nil)
|
16
|
+
@_collection = nil unless collection_name.nil?
|
17
|
+
@_collection ||= database[collection_name]
|
18
|
+
end
|
19
|
+
|
20
|
+
# configuration shortcut
|
21
|
+
def mongo(options)
|
22
|
+
connection *options[:connection] if options.member?(:connection)
|
23
|
+
database options[:database] if options.member?(:database)
|
24
|
+
collection options[:collection] if options.member?(:collection)
|
25
|
+
end
|
26
|
+
|
27
|
+
# -------------------------------------------------------------------------
|
28
|
+
|
29
|
+
def ensure_collection
|
30
|
+
database.create_collection(collection.name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def drop_collection!
|
34
|
+
collection.drop
|
35
|
+
end
|
36
|
+
|
37
|
+
def recreate_collection!
|
38
|
+
drop_collection! and ensure_collection
|
39
|
+
end
|
40
|
+
|
41
|
+
def identity_map
|
42
|
+
raise RuntimeError, "please set the mongo database first" unless database
|
43
|
+
raise RuntimeError, "please set the mongo collection first" unless collection
|
44
|
+
Zentradi::IdentityMap[database.name, collection.name]
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Zentradi
|
2
|
+
class Document
|
3
|
+
|
4
|
+
extend Connection
|
5
|
+
extend ClassHelpers
|
6
|
+
extend Instantiators
|
7
|
+
|
8
|
+
attr_accessor :document
|
9
|
+
instance_access_to_class_methods :identity_map, :collection
|
10
|
+
|
11
|
+
def initialize(document = nil)
|
12
|
+
raise ArgumentError, "provide a Hash like object or no parameters" unless document.nil? || document.class.ancestors.include?(Hash)
|
13
|
+
|
14
|
+
@document = document ? Hashie::Mash.new(document) : Hashie::Mash.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def update(document)
|
18
|
+
@document.update(document) and save
|
19
|
+
end
|
20
|
+
|
21
|
+
def update!(document)
|
22
|
+
@document.update(document) and save!
|
23
|
+
end
|
24
|
+
|
25
|
+
def [](key)
|
26
|
+
@document[key]
|
27
|
+
end
|
28
|
+
|
29
|
+
def []=(key, value)
|
30
|
+
@document[key] = value
|
31
|
+
end
|
32
|
+
|
33
|
+
def id
|
34
|
+
@document["_id"]
|
35
|
+
end
|
36
|
+
|
37
|
+
def new?
|
38
|
+
not saved?
|
39
|
+
end
|
40
|
+
|
41
|
+
def saved?
|
42
|
+
id && collection.find("_id" => id).count != 0
|
43
|
+
end
|
44
|
+
|
45
|
+
def save(safe = false)
|
46
|
+
if id
|
47
|
+
collection.update({"_id" => id}, @document, :safe => safe)
|
48
|
+
else
|
49
|
+
update("_id" => collection.save(@document, :safe => safe))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def save!
|
54
|
+
save(true)
|
55
|
+
end
|
56
|
+
|
57
|
+
def destroy
|
58
|
+
if id
|
59
|
+
collection.remove("_id" => id)
|
60
|
+
@document.delete("_id")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def reload
|
65
|
+
if _id = id
|
66
|
+
@document.clear["_id"] = _id # clear and set.
|
67
|
+
update(mongo_document)
|
68
|
+
end
|
69
|
+
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def mongo_document
|
75
|
+
raise RuntimeError, "cannot retrieve a new document" if new?
|
76
|
+
|
77
|
+
collection.find_one("_id" => id).tap do |i|
|
78
|
+
raise RuntimeError, "nothing was retrieved while loading the mongo instance ( #{ i.inspect } )" if i.nil? || i.empty?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Zentradi
|
2
|
+
# NOTE: WIP, not working yet.
|
3
|
+
#
|
4
|
+
# Stores weak references to objects to ensure only one
|
5
|
+
# instance of a ruby class is used for holding a reference
|
6
|
+
# to a specific mongo collection.
|
7
|
+
class IdentityMap
|
8
|
+
class << self
|
9
|
+
# one identity map per db/collection tuple
|
10
|
+
def [](db_name, collection_name)
|
11
|
+
@hash ||= Hash.new { |h,k| h[k] = Hash.new { |hh, kk| hh[kk] = IdentityMap.new } }
|
12
|
+
@hash[db_name][collection_name]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@map = WeakHash.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# retrieves a document with given _id
|
21
|
+
def get(_id)
|
22
|
+
@map[_id].tap { |instance| check(_id, instance) }
|
23
|
+
end
|
24
|
+
|
25
|
+
# stores a reference to the mongo document.
|
26
|
+
def set(_id, instance)
|
27
|
+
check(_id, @map[_id] = instance)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def check(_id, instance)
|
32
|
+
raise ArgumentError, "instance must be a Zentradi::Document" unless instance.nil? || instance.is_a?(Zentradi::Document)
|
33
|
+
raise RuntimeError, "instance #{ instance.inspect } does not match _id: #{ _id }" if instance && ( instance.id != _id )
|
34
|
+
instance
|
35
|
+
end
|
36
|
+
|
37
|
+
# Some helper methods to enable / disable the identity map at a class level.
|
38
|
+
module Management
|
39
|
+
def enable_identity_map
|
40
|
+
@_identity_map = true
|
41
|
+
end
|
42
|
+
|
43
|
+
def disable_identity_map
|
44
|
+
@_identity_map = false
|
45
|
+
end
|
46
|
+
|
47
|
+
# enabled by default
|
48
|
+
def identity_map_enabled?
|
49
|
+
@_identity_map.nil? || @_identity_map
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def fetch_instance(param_doc)
|
55
|
+
if param_doc.nil?
|
56
|
+
nil
|
57
|
+
elsif identity_map_enabled? && param_doc["_id"]
|
58
|
+
|
59
|
+
if instance = identity_map.get(param_doc["_id"])
|
60
|
+
instance.update(param_doc)
|
61
|
+
else
|
62
|
+
document = param_doc.is_a?(Document) ? param_doc : new(param_doc)
|
63
|
+
instance = identity_map.set(document["_id"], document)
|
64
|
+
end
|
65
|
+
|
66
|
+
instance
|
67
|
+
else
|
68
|
+
param_doc.is_a?(Document) ? param_doc : new(param_doc)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end # end module Management
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Zentradi
|
2
|
+
module Instantiators
|
3
|
+
extend ClassHelpers
|
4
|
+
|
5
|
+
delegate :remove, :update, :to => :collection
|
6
|
+
|
7
|
+
def all(params = nil)
|
8
|
+
collection.find(params).map(&method(:instantiate))
|
9
|
+
end
|
10
|
+
|
11
|
+
def first(params = nil)
|
12
|
+
query = params.is_a?(String) || params.is_a?(Numeric) ? {"_id" => params} : params
|
13
|
+
|
14
|
+
instantiate collection.find_one(query)
|
15
|
+
end
|
16
|
+
|
17
|
+
def find_or_initialize(params)
|
18
|
+
raise RuntimeError, "cannot find a document without params" if params.nil?
|
19
|
+
|
20
|
+
first(params) || instantiate(params)
|
21
|
+
end
|
22
|
+
|
23
|
+
def create(params)
|
24
|
+
instantiate(params).tap { |n| n.save }
|
25
|
+
end
|
26
|
+
|
27
|
+
def create!(params)
|
28
|
+
instantiate(params).tap { |n| n.save! }
|
29
|
+
end
|
30
|
+
|
31
|
+
def instantiate(document)
|
32
|
+
document ? new(document) : nil
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'zentradi'
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Post < Zentradi::Document
|
4
|
+
mongo :collection => "post", :database => "zentradi"
|
5
|
+
|
6
|
+
mongo_accessor :title
|
7
|
+
end
|
8
|
+
|
9
|
+
describe Zentradi::Document do
|
10
|
+
before do
|
11
|
+
Post.remove
|
12
|
+
end
|
13
|
+
|
14
|
+
it "creates a document" do
|
15
|
+
post = Post.new
|
16
|
+
post.id.should be_nil
|
17
|
+
post.should be_new
|
18
|
+
|
19
|
+
post.save
|
20
|
+
|
21
|
+
post.id.should_not be_nil
|
22
|
+
post.should_not be_new
|
23
|
+
end
|
24
|
+
|
25
|
+
it "finds a document through the identity map" do
|
26
|
+
@post = Post.create(:title => "Hola Mundo", :body => "Hi.")
|
27
|
+
Post.first("_id" => @post.id).should be_an_instance_of(Post)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "finds or initializes a document" do
|
31
|
+
@post = Post.create(:title => "Test")
|
32
|
+
|
33
|
+
found = Post.find_or_initialize(:title => "Test")
|
34
|
+
found.title.should == "Test"
|
35
|
+
|
36
|
+
found = Post.find_or_initialize(:title => "Test 2")
|
37
|
+
found.title.should == "Test 2"
|
38
|
+
found.should be_new
|
39
|
+
found.save
|
40
|
+
|
41
|
+
found.should_not be_new
|
42
|
+
found.title.should == "Test 2"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "updates a document" do
|
46
|
+
@post = Post.create(:title => "Hola Mundo", :body => "Hi.")
|
47
|
+
@post.title = "ABC"
|
48
|
+
@post.save
|
49
|
+
@post.reload
|
50
|
+
@post.title.should == "ABC"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "destroys a document" do
|
54
|
+
@post = Post.create(:title => "Hola Mundo", :body => "Hi.")
|
55
|
+
id = @post.id
|
56
|
+
@post.should_not be_new
|
57
|
+
@post.destroy
|
58
|
+
Post.first(id).should be_nil
|
59
|
+
end
|
60
|
+
|
61
|
+
it "finds all the documents" do
|
62
|
+
Post.remove
|
63
|
+
Post.create(:title => "First")
|
64
|
+
Post.create(:title => "Second")
|
65
|
+
Post.all.map(&:title).should include("First")
|
66
|
+
Post.all.map(&:title).should include("Second")
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zentradi::IdentityMap do
|
4
|
+
before do
|
5
|
+
@oh = Zentradi::Document.new
|
6
|
+
@oh["_id"] = "123456"
|
7
|
+
|
8
|
+
@im = Zentradi::IdentityMap["a_db", "a_collection"]
|
9
|
+
|
10
|
+
GC.start # make sure @im is collected if it was overwritten (e.g. in second example run)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "stores an object" do
|
14
|
+
@im.set("123456", @oh)
|
15
|
+
@im.get("123456").should == @oh
|
16
|
+
end
|
17
|
+
|
18
|
+
it "stores a weak reference" do
|
19
|
+
@im.set("123456", @oh)
|
20
|
+
@im.get("123456").should == @oh
|
21
|
+
|
22
|
+
@oh = nil; GC.start
|
23
|
+
|
24
|
+
@im.get("123456").should be_nil
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Book < Zentradi::Document
|
4
|
+
mongo :collection => "books", :database => "zentradi"
|
5
|
+
|
6
|
+
mongo_accessor :checksum
|
7
|
+
end
|
8
|
+
|
9
|
+
describe Zentradi, "managing indexes" do
|
10
|
+
before do
|
11
|
+
Book.recreate_collection!
|
12
|
+
end
|
13
|
+
|
14
|
+
it "is able to create indexes" do
|
15
|
+
Book.collection.create_index "checksum", true
|
16
|
+
#Book.collection.create_index([[ "checksum", Mongo::ASCENDING ]], true)
|
17
|
+
Book.collection.index_information.keys.detect { |k| k =~ /checksum/ }.should be_true
|
18
|
+
end
|
19
|
+
|
20
|
+
it "throws an error if we insert the same value twice on an unique index column" do
|
21
|
+
Book.collection.create_index "checksum", true
|
22
|
+
Book.create(checksum: 1234)
|
23
|
+
lambda { Book.create!(checksum: 1234) }.should raise_error(Mongo::OperationFailure)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
metadata
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: zentradi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 0.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Emmanuel Oga
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-03-16 00:00:00 -03:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 2
|
30
|
+
- 9
|
31
|
+
version: 1.2.9
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rake
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
44
|
+
type: :development
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: mongo
|
48
|
+
prerelease: false
|
49
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
segments:
|
54
|
+
- 0
|
55
|
+
version: "0"
|
56
|
+
type: :runtime
|
57
|
+
version_requirements: *id003
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: mongo_ext
|
60
|
+
prerelease: false
|
61
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
segments:
|
66
|
+
- 0
|
67
|
+
version: "0"
|
68
|
+
type: :runtime
|
69
|
+
version_requirements: *id004
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: weak_hash
|
72
|
+
prerelease: false
|
73
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
version: "0"
|
80
|
+
type: :runtime
|
81
|
+
version_requirements: *id005
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: hashie
|
84
|
+
prerelease: false
|
85
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
version: "0"
|
92
|
+
type: :runtime
|
93
|
+
version_requirements: *id006
|
94
|
+
description: minimalistic tools for accessing mongodb
|
95
|
+
email: EmmanuelOga@gmail.com
|
96
|
+
executables: []
|
97
|
+
|
98
|
+
extensions: []
|
99
|
+
|
100
|
+
extra_rdoc_files:
|
101
|
+
- LICENSE
|
102
|
+
- README.rdoc
|
103
|
+
files:
|
104
|
+
- .document
|
105
|
+
- .gitignore
|
106
|
+
- Gemfile
|
107
|
+
- LICENSE
|
108
|
+
- README.rdoc
|
109
|
+
- Rakefile
|
110
|
+
- VERSION
|
111
|
+
- lib/zentradi.rb
|
112
|
+
- lib/zentradi/class_helpers.rb
|
113
|
+
- lib/zentradi/connection.rb
|
114
|
+
- lib/zentradi/document.rb
|
115
|
+
- lib/zentradi/identity_map.rb
|
116
|
+
- lib/zentradi/instantiators.rb
|
117
|
+
- spec/spec_helper.rb
|
118
|
+
- spec/zentradi/document_spec.rb
|
119
|
+
- spec/zentradi/identity_map_spec.rb
|
120
|
+
- spec/zentradi/indexes_spec.rb
|
121
|
+
- spec/zentradi_spec.rb
|
122
|
+
has_rdoc: true
|
123
|
+
homepage: http://github.com/EmmanuelOga/zentradi
|
124
|
+
licenses: []
|
125
|
+
|
126
|
+
post_install_message:
|
127
|
+
rdoc_options:
|
128
|
+
- --charset=UTF-8
|
129
|
+
require_paths:
|
130
|
+
- lib
|
131
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
segments:
|
136
|
+
- 0
|
137
|
+
version: "0"
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
segments:
|
143
|
+
- 0
|
144
|
+
version: "0"
|
145
|
+
requirements: []
|
146
|
+
|
147
|
+
rubyforge_project:
|
148
|
+
rubygems_version: 1.3.6
|
149
|
+
signing_key:
|
150
|
+
specification_version: 3
|
151
|
+
summary: minimalistic tools for accessing mongodb
|
152
|
+
test_files:
|
153
|
+
- spec/zentradi_spec.rb
|
154
|
+
- spec/zentradi/document_spec.rb
|
155
|
+
- spec/zentradi/identity_map_spec.rb
|
156
|
+
- spec/zentradi/indexes_spec.rb
|
157
|
+
- spec/spec_helper.rb
|