zentradi 0.0.0 → 0.0.1

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/README.rdoc CHANGED
@@ -61,7 +61,7 @@ In particular, I want:
61
61
  [
62
62
  "magic",
63
63
  "ruby hooks overrides",
64
- "additions to the mongo mapper API",
64
+ "additions to the mongo driver API",
65
65
  "plugins paraphernalia",
66
66
  "use and abuse of generated methods -- find_by_blah_blah anyone? -- ",
67
67
  "features of ActiveRecord, Datamapper, [INSERT ORM HERE]"
data/Rakefile CHANGED
@@ -22,7 +22,6 @@ begin
22
22
  gem.add_development_dependency "rake"
23
23
  gem.add_dependency "mongo"
24
24
  gem.add_dependency "mongo_ext"
25
- gem.add_dependency "weak_hash"
26
25
  gem.add_dependency "hashie"
27
26
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
28
27
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.0.1
data/lib/zentradi.rb CHANGED
@@ -1,13 +1,18 @@
1
1
  require 'hashie'
2
- require 'weak_hash'
3
2
  require 'mongo'
4
3
 
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'
4
+ module Zdi
5
+ autoload :Delegate , 'zentradi/delegate'
6
+ autoload :DocumentWrapper , 'zentradi/document_wrapper'
7
+ autoload :Collection , 'zentradi/collection'
8
+
9
+ class << self
10
+ attr_accessor :default_database
11
+
12
+ def Collection(collection, database = Zdi.default_database)
13
+ Class.new(Zdi::Collection) do
14
+ instance_variable_set("@collection", database[collection])
15
+ end
16
+ end
17
+ end
13
18
  end
@@ -0,0 +1,56 @@
1
+ module Zdi
2
+ class Collection
3
+ class << self
4
+ extend Zdi::Delegate
5
+ delegate *(Mongo::Collection.public_instance_methods - public_instance_methods), :to => :collection
6
+ end
7
+
8
+ module ClassMethods
9
+ attr_accessor :collection
10
+
11
+ def inherited(base)
12
+ base.collection = self.collection
13
+ end
14
+
15
+ def ensure_collection
16
+ database.create_collection(collection.name)
17
+ end
18
+
19
+ def drop_collection
20
+ collection.drop
21
+ end
22
+
23
+ def recreate_collection
24
+ drop_collection; ensure_collection
25
+ end
26
+
27
+ def build(attributes = {})
28
+ DocumentWrapper.new(self, attributes)
29
+ end
30
+
31
+ def create(attributes = {})
32
+ doc = build(attributes)
33
+ doc.save
34
+ doc
35
+ end
36
+
37
+ def find_or_build(attributes)
38
+ find_one(attributes) || build(attributes)
39
+ end
40
+
41
+ def find_or_create(attributes)
42
+ update(attributes, attributes, :upsert => true)
43
+ end
44
+
45
+ def all
46
+ find
47
+ end
48
+ end
49
+
50
+ extend ClassMethods
51
+
52
+ class << self
53
+ alias_method :first, :find_one
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,32 @@
1
+ module Zdi
2
+ module Delegate
3
+ def delegate(*methods)
4
+ include Wrapper unless ancestors.include?(Wrapper)
5
+ to = methods.pop[:to]
6
+ methods.each do |name|
7
+ module_eval(<<-EOMETHOD, __FILE__, __LINE__ + 1)
8
+ def #{ name }(*args, &block)
9
+ new_args = args.map { |a| a.is_a?(DocumentWrapper) ? a.to_hash : a }
10
+
11
+ result = #{to}.send :#{name}, *new_args, &block
12
+
13
+ return wrap_if_document(result)
14
+ end
15
+ EOMETHOD
16
+ end
17
+ end
18
+
19
+ module Wrapper
20
+ def wrap_if_document(object)
21
+ if object.is_a?(OrderedHash)
22
+ DocumentWrapper.new(self, object)
23
+ elsif object.respond_to?(:map)
24
+ object.map { |e| wrap_if_document(e) }
25
+ else
26
+ return object
27
+ end
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,38 @@
1
+ module Zdi
2
+ class DocumentWrapper < Hashie::Mash
3
+
4
+ attr_reader :collection
5
+
6
+ def initialize(collection, hash = {})
7
+ super(hash)
8
+ @collection = collection
9
+ end
10
+
11
+ def id
12
+ super || _id
13
+ end
14
+
15
+ def new?
16
+ id.nil? || @collection.find("_id" => id).count == 0
17
+ end
18
+
19
+ def save
20
+ if id.nil?
21
+ self.id = @collection.save(self)
22
+ else
23
+ @collection.update({"_id" => id}, self)
24
+ end
25
+ self
26
+ end
27
+
28
+ def update(attributes)
29
+ super(attributes)
30
+ save
31
+ end
32
+
33
+ def destroy
34
+ @collection.remove("_id" => id)
35
+ end
36
+
37
+ end
38
+ end
data/spec/spec_helper.rb CHANGED
@@ -1 +1,3 @@
1
1
  require 'zentradi'
2
+
3
+ Zdi.default_database = Mongo::Connection.new.db("zentradi")
@@ -1,19 +1,14 @@
1
1
  require 'spec_helper'
2
2
 
3
- class Post < Zentradi::Document
4
- mongo :collection => "post", :database => "zentradi"
3
+ Post = Zdi::Collection("posts")
5
4
 
6
- mongo_accessor :title
7
- end
8
-
9
- describe Zentradi::Document do
5
+ describe Zdi::Collection do
10
6
  before do
11
7
  Post.remove
12
8
  end
13
9
 
14
10
  it "creates a document" do
15
- post = Post.new
16
- post.id.should be_nil
11
+ post = Post.build
17
12
  post.should be_new
18
13
 
19
14
  post.save
@@ -22,18 +17,14 @@ describe Zentradi::Document do
22
17
  post.should_not be_new
23
18
  end
24
19
 
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
20
 
30
21
  it "finds or initializes a document" do
31
22
  @post = Post.create(:title => "Test")
32
23
 
33
- found = Post.find_or_initialize(:title => "Test")
24
+ found = Post.find_or_build(:title => "Test")
34
25
  found.title.should == "Test"
35
26
 
36
- found = Post.find_or_initialize(:title => "Test 2")
27
+ found = Post.find_or_build(:title => "Test 2")
37
28
  found.title.should == "Test 2"
38
29
  found.should be_new
39
30
  found.save
@@ -43,11 +34,14 @@ describe Zentradi::Document do
43
34
  end
44
35
 
45
36
  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"
37
+ post = Post.create(:title => "Hola Mundo", :body => "Hi.")
38
+ post.title = "ABC"
39
+ post.save
40
+
41
+ post.update(:title => post.title + " DEF")
42
+
43
+ from_db = Post.first("_id" => post.id)
44
+ from_db.title.should == "ABC DEF"
51
45
  end
52
46
 
53
47
  it "destroys a document" do
@@ -1,3 +1,4 @@
1
+ __END__
1
2
  require 'spec_helper'
2
3
 
3
4
  class Book < Zentradi::Document
data/zentradi.gemspec ADDED
@@ -0,0 +1,72 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{zentradi}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Emmanuel Oga"]
12
+ s.date = %q{2010-03-29}
13
+ s.description = %q{minimalistic tools for accessing mongodb}
14
+ s.email = %q{EmmanuelOga@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "Gemfile",
23
+ "LICENSE",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "lib/zentradi.rb",
28
+ "lib/zentradi/collection.rb",
29
+ "lib/zentradi/delegate.rb",
30
+ "lib/zentradi/document_wrapper.rb",
31
+ "spec/spec_helper.rb",
32
+ "spec/zentradi/document_spec.rb",
33
+ "spec/zentradi/indexes_spec.rb",
34
+ "zentradi.gemspec"
35
+ ]
36
+ s.homepage = %q{http://github.com/EmmanuelOga/zentradi}
37
+ s.rdoc_options = ["--charset=UTF-8"]
38
+ s.require_paths = ["lib"]
39
+ s.rubygems_version = %q{1.3.6}
40
+ s.summary = %q{minimalistic tools for accessing mongodb}
41
+ s.test_files = [
42
+ "spec/zentradi/document_spec.rb",
43
+ "spec/zentradi/indexes_spec.rb",
44
+ "spec/spec_helper.rb"
45
+ ]
46
+
47
+ if s.respond_to? :specification_version then
48
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
49
+ s.specification_version = 3
50
+
51
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
52
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
53
+ s.add_development_dependency(%q<rake>, [">= 0"])
54
+ s.add_runtime_dependency(%q<mongo>, [">= 0"])
55
+ s.add_runtime_dependency(%q<mongo_ext>, [">= 0"])
56
+ s.add_runtime_dependency(%q<hashie>, [">= 0"])
57
+ else
58
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
59
+ s.add_dependency(%q<rake>, [">= 0"])
60
+ s.add_dependency(%q<mongo>, [">= 0"])
61
+ s.add_dependency(%q<mongo_ext>, [">= 0"])
62
+ s.add_dependency(%q<hashie>, [">= 0"])
63
+ end
64
+ else
65
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
66
+ s.add_dependency(%q<rake>, [">= 0"])
67
+ s.add_dependency(%q<mongo>, [">= 0"])
68
+ s.add_dependency(%q<mongo_ext>, [">= 0"])
69
+ s.add_dependency(%q<hashie>, [">= 0"])
70
+ end
71
+ end
72
+
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 0
9
- version: 0.0.0
8
+ - 1
9
+ version: 0.0.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Emmanuel Oga
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-16 00:00:00 -03:00
17
+ date: 2010-03-29 00:00:00 -03:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -68,7 +68,7 @@ dependencies:
68
68
  type: :runtime
69
69
  version_requirements: *id004
70
70
  - !ruby/object:Gem::Dependency
71
- name: weak_hash
71
+ name: hashie
72
72
  prerelease: false
73
73
  requirement: &id005 !ruby/object:Gem::Requirement
74
74
  requirements:
@@ -79,18 +79,6 @@ dependencies:
79
79
  version: "0"
80
80
  type: :runtime
81
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
82
  description: minimalistic tools for accessing mongodb
95
83
  email: EmmanuelOga@gmail.com
96
84
  executables: []
@@ -109,16 +97,13 @@ files:
109
97
  - Rakefile
110
98
  - VERSION
111
99
  - 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
100
+ - lib/zentradi/collection.rb
101
+ - lib/zentradi/delegate.rb
102
+ - lib/zentradi/document_wrapper.rb
117
103
  - spec/spec_helper.rb
118
104
  - spec/zentradi/document_spec.rb
119
- - spec/zentradi/identity_map_spec.rb
120
105
  - spec/zentradi/indexes_spec.rb
121
- - spec/zentradi_spec.rb
106
+ - zentradi.gemspec
122
107
  has_rdoc: true
123
108
  homepage: http://github.com/EmmanuelOga/zentradi
124
109
  licenses: []
@@ -150,8 +135,6 @@ signing_key:
150
135
  specification_version: 3
151
136
  summary: minimalistic tools for accessing mongodb
152
137
  test_files:
153
- - spec/zentradi_spec.rb
154
138
  - spec/zentradi/document_spec.rb
155
- - spec/zentradi/identity_map_spec.rb
156
139
  - spec/zentradi/indexes_spec.rb
157
140
  - spec/spec_helper.rb
@@ -1,46 +0,0 @@
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
@@ -1,48 +0,0 @@
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
@@ -1,83 +0,0 @@
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
@@ -1,75 +0,0 @@
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
@@ -1,36 +0,0 @@
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
@@ -1,26 +0,0 @@
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
@@ -1,7 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Zentradi do
4
- it "works" do
5
- true.should be_true
6
- end
7
- end