mongodb 2.0.2 → 2.1.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/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'rake_ext'
2
2
 
3
3
  project \
4
4
  name: "mongodb",
5
- # version: '2.0.0',
5
+ version: '2.1.0',
6
6
  gem: true,
7
7
  summary: "Persistence for any Ruby Object & Driver enhancements for MongoDB.",
8
8
 
@@ -1,4 +1,4 @@
1
- module Mongo::CollectionHelper
1
+ module Mongo::Object::CollectionHelper
2
2
  # CRUD.
3
3
 
4
4
  def create_with_object doc, options = {}
@@ -55,12 +55,13 @@ module Mongo::CollectionHelper
55
55
 
56
56
  # Querying.
57
57
 
58
- def first selector = {}, options = {}, &block
58
+ def first selector = {}, options = {}
59
59
  options = options.clone
60
60
  if options.delete(:object) == false
61
- super selector, options, &block
61
+ super selector, options
62
62
  else
63
- ::Mongo::Object.build super(selector, options, &block)
63
+ doc = super(selector, options)
64
+ build doc
64
65
  end
65
66
  end
66
67
 
@@ -70,8 +71,22 @@ module Mongo::CollectionHelper
70
71
  super selector, options, &block
71
72
  else
72
73
  super selector, options do |doc|
73
- block.call ::Mongo::Object.build(doc)
74
+ block.call build(doc)
74
75
  end
75
76
  end
76
77
  end
78
+
79
+ protected
80
+ def build doc
81
+ if doc and (class_name = doc['_class'])
82
+ klass = Mongo::Object.constantize class_name
83
+ if klass.respond_to? :from_mongo
84
+ klass.from_mongo doc
85
+ else
86
+ Mongo::Object.from_mongo doc
87
+ end
88
+ else
89
+ doc
90
+ end
91
+ end
77
92
  end
@@ -3,7 +3,7 @@ require 'mongo/object/object'
3
3
  require 'mongo/object/collection_helper'
4
4
 
5
5
  Mongo::Collection.class_eval do
6
- include Mongo::CollectionHelper
6
+ include Mongo::Object::CollectionHelper
7
7
 
8
8
  %w(create update save delete).each do |method|
9
9
  alias_method "#{method}_without_object", method
@@ -1,18 +1,21 @@
1
1
  module Mongo::Object
2
- attr_accessor :_id, :_parent
2
+ attr_accessor :_id, :_parent, :_not_new
3
3
 
4
4
  def _id?; !!_id end
5
- def new?; !_id end
6
- alias_method :new_record?, :new?
5
+
6
+ def new?; !_not_new end
7
7
 
8
8
  def create_object collection, options
9
9
  doc = to_mongo
10
10
 
11
11
  # Generating custom id if option enabled.
12
- doc['_id'] = generate_id if Mongo.defaults[:generate_id]
12
+ doc['_id'] ||= generate_id if Mongo.defaults[:generate_id]
13
13
 
14
14
  id = collection.create doc, options
15
- self._id = id
15
+
16
+ self._id ||= id
17
+ self._not_new = true
18
+
16
19
  id
17
20
  end
18
21
 
@@ -28,7 +31,7 @@ module Mongo::Object
28
31
  end
29
32
 
30
33
  def save_object collection, options
31
- if _id
34
+ if _not_new
32
35
  update_object collection, options
33
36
  else
34
37
  create_object collection, options
@@ -43,23 +46,27 @@ module Mongo::Object
43
46
 
44
47
  # Convert object to document (with nested documents & arrays).
45
48
  def to_mongo
46
- {}.tap do |h|
47
- # Copy instance variables.
48
- persistent_instance_variable_names.each do |iv_name|
49
- k = iv_name.to_s[1..-1]
50
- v = instance_variable_get iv_name
51
- h[k] = v.to_mongo
52
- end
49
+ convert_object self, :_to_mongo
50
+ end
53
51
 
54
- # Adding _id & _class.
55
- h['_id'] = _id if _id
56
- h['_class'] = self.class.name || \
57
- raise("unknow class name for model #{h.inspect}!")
52
+ def _to_mongo options = {}
53
+ h = {}
54
+ # Copy instance variables.
55
+ persistent_instance_variable_names.each do |iv_name|
56
+ k = iv_name.to_s[1..-1]
57
+ v = instance_variable_get iv_name
58
+ h[k] = convert_object v, :_to_mongo
58
59
  end
60
+
61
+ # Adding _id & _class.
62
+ h['_id'] = _id if _id
63
+ h['_class'] = self.class.name || \
64
+ raise("unknow class name for model #{h.inspect}!")
65
+ h
59
66
  end
60
67
 
61
68
  def to_hash
62
- {}.tap{|h| to_mongo.each{|k, v| h[k.to_sym] = v}}
69
+ Hash.respond_to?(:symbolize) ? Hash.symbolize(to_mongo) : to_mongo
63
70
  end
64
71
 
65
72
  # Override it to generate Your custom ids.
@@ -75,6 +82,19 @@ module Mongo::Object
75
82
  alias_method :to_s, :inspect
76
83
 
77
84
  protected
85
+ def convert_object obj, method, options = {}
86
+ if obj.respond_to? :collect_with_value
87
+ # Array or Hash.
88
+ obj.collect_with_value{|v| convert_object v, method, options}
89
+ elsif obj.respond_to method
90
+ # Object.
91
+ obj.public_send method, options
92
+ else
93
+ # Simple object.
94
+ obj
95
+ end
96
+ end
97
+
78
98
  ID_SYMBOLS = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a
79
99
  def generate_random_string_id
80
100
  id, size = "", Mongo.defaults[:random_string_id_size]
@@ -83,52 +103,47 @@ module Mongo::Object
83
103
  end
84
104
 
85
105
  class << self
86
- def build doc
87
- doc && _build(doc, nil)
106
+ def from_mongo doc
107
+ _from_mongo doc, nil
108
+ end
109
+
110
+ def constantize class_name
111
+ @constantize_cache ||= {}
112
+ unless klass = @constantize_cache[class_name]
113
+ klass = eval class_name, TOPLEVEL_BINDING, __FILE__, __LINE__
114
+ @constantize_cache[class_name] = klass
115
+ end
116
+ klass
88
117
  end
89
118
 
90
119
  protected
91
- def _build doc, parent = nil
120
+ def _from_mongo doc, parent = nil
92
121
  if doc.is_a? Hash
93
- if class_name = doc[:_class] || doc['_class']
122
+ if class_name = doc['_class']
94
123
  klass = constantize class_name
124
+ obj = klass.new
95
125
 
96
- # Unmarshalling object.
97
- if klass.respond_to? :from_mongo
98
- obj = klass.from_mongo doc
99
- else
100
- obj = klass.new
101
- parent ||= obj
102
- doc.each do |k, v|
103
- v = _build v, parent
104
- obj.instance_variable_set "@#{k}", v
105
- end
106
- obj
107
- end
126
+ obj._not_new = true
108
127
  obj._parent = parent if parent
109
128
 
110
- # Firing special after build callback if defined.
111
- obj.run_after_callbacks :build, :build if obj.respond_to? :run_after_callbacks
129
+ doc.each do |k, v|
130
+ v = _from_mongo v, obj
131
+ obj.instance_variable_set "@#{k}", v
132
+ end
112
133
 
113
134
  obj
114
135
  else
115
- {}.tap{|h| doc.each{|k, v| h[k] = _build v, parent}}
136
+ {}.tap{|h| doc.each{|k, v| h[k] = _from_mongo v, parent}}
116
137
  end
117
138
  elsif doc.is_a? Array
118
- doc.collect{|v| _build v, parent}
139
+ a = doc.collect{|v| _from_mongo v, parent}
140
+ # Array also can be a model at the same time.
141
+ a._parent = parent if parent and a.respond_to?(:_parent=)
142
+ a
119
143
  else
120
144
  # Simple type.
121
145
  doc
122
146
  end
123
147
  end
124
-
125
- def constantize class_name
126
- @constantize_cache ||= {}
127
- unless klass = @constantize_cache[class_name]
128
- klass = eval class_name, TOPLEVEL_BINDING, __FILE__, __LINE__
129
- @constantize_cache[class_name] = klass
130
- end
131
- klass
132
- end
133
148
  end
134
149
  end
@@ -92,6 +92,7 @@ shared_examples_for 'embedded object CRUD' do
92
92
  it "embedded object should have :_parent reference to the main object" do
93
93
  db.units.save @unit
94
94
  unit = db.units.first
95
+ unit._parent.should be_nil
95
96
  unit.items.first._parent.should == unit
96
97
  end
97
98
 
@@ -1,15 +1,10 @@
1
- Object.class_eval do
2
- def to_mongo; self end
3
- end
4
-
5
1
  Array.class_eval do
6
- def to_mongo
7
- collect{|v| v.to_mongo}
8
- end
2
+ alias_method :each_value, :each
3
+ alias_method :collect_with_value, :collect
9
4
  end
10
5
 
11
6
  Hash.class_eval do
12
- def to_mongo
13
- {}.tap{|h| each{|k, v| h[k] = v.to_mongo}}
7
+ def collect_with_value &block
8
+ {}.tap{|h| self.each{|k, v| h[k] = block.call v}}
14
9
  end
15
10
  end
@@ -1 +1 @@
1
- gem 'mongo', '~> 1.4'
1
+ gem 'mongo', '~> 1.5'
@@ -41,7 +41,7 @@ describe "Object CRUD" do
41
41
  include Mongo::Object
42
42
 
43
43
  attr_accessor :name
44
- def == o; [self.class, self.name] == [o.class, o.name] end
44
+ def == o; (self.class == o.class) and (self.name == o.name) end
45
45
  end
46
46
  end
47
47
 
@@ -0,0 +1,78 @@
1
+ require 'object/spec_helper'
2
+
3
+ describe "Object" do
4
+ with_mongo
5
+
6
+ old = Mongo.defaults[:generate_id] = false
7
+ before do
8
+ Mongo.defaults[:generate_id] = true
9
+ class Tmp
10
+ include Mongo::Object
11
+ end
12
+ end
13
+ after do
14
+ Mongo.defaults[:generate_id] = old
15
+ remove_constants :Tmp, :Comment, :Tags
16
+ end
17
+
18
+ after{remove_constants :Post, :Tags}
19
+
20
+ it "should use autogenerated random string id (if specified, instead of default BSON::ObjectId)" do
21
+ o = Tmp.new
22
+ db.objects.save o
23
+ o._id.should be_a(String)
24
+ o._id.size.should == Mongo.defaults[:random_string_id_size]
25
+ end
26
+
27
+ it "shoud convert to hash" do
28
+ class Tmp
29
+ attr_accessor :name
30
+ end
31
+ o = Tmp.new
32
+ o.name = 'some name'
33
+ o.to_hash.should == {name: 'some name', _class: 'Tmp'}
34
+ end
35
+
36
+ it "should convert object to mongo and to Hash" do
37
+ class Post
38
+ include Mongo::Object
39
+
40
+ attr_accessor :title, :tags, :comments
41
+ end
42
+
43
+ class Comment
44
+ include Mongo::Object
45
+
46
+ attr_accessor :text
47
+ end
48
+
49
+ class Tags < Array
50
+ include Mongo::Object
51
+ end
52
+
53
+ comment = Comment.new
54
+ comment.text = 'Some text'
55
+
56
+ tags = Tags.new
57
+ tags.push 'a', 'b'
58
+
59
+ post = Post.new
60
+ post.title = 'Some title'
61
+ post.comments = [comment]
62
+ post.tags = tags
63
+
64
+ post.to_mongo.should == {
65
+ "_class" => "Post",
66
+ "title" => 'Some title',
67
+ "comments" => [{"text" => "Some text", "_class" => "Comment"}],
68
+ "tags" => ['a', 'b']
69
+ }
70
+
71
+ post.to_hash.should == {
72
+ _class: "Post",
73
+ title: 'Some title',
74
+ comments: [{text: "Some text", _class: "Comment"}],
75
+ tags: ['a', 'b']
76
+ }
77
+ end
78
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongodb
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,19 +9,19 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-19 00:00:00.000000000Z
12
+ date: 2011-12-19 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mongo
16
- requirement: &2849860 !ruby/object:Gem::Requirement
16
+ requirement: &70332531962700 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: '1.4'
21
+ version: '1.5'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2849860
24
+ version_requirements: *70332531962700
25
25
  description:
26
26
  email:
27
27
  executables: []
@@ -57,8 +57,8 @@ files:
57
57
  - spec/driver/hash_crud_spec.rb
58
58
  - spec/driver/spec_helper.rb
59
59
  - spec/migration/migration_spec.rb
60
- - spec/object/miscellaneous_spec.rb
61
60
  - spec/object/object_crud_spec.rb
61
+ - spec/object/object_spec.rb
62
62
  - spec/object/spec_helper.rb
63
63
  homepage: http://alexeypetrushin.github.com/mongodb
64
64
  licenses: []
@@ -80,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
80
  version: '0'
81
81
  requirements: []
82
82
  rubyforge_project:
83
- rubygems_version: 1.8.6
83
+ rubygems_version: 1.8.10
84
84
  signing_key:
85
85
  specification_version: 3
86
86
  summary: Persistence for any Ruby Object & Driver enhancements for MongoDB.
@@ -1,32 +0,0 @@
1
- require 'object/spec_helper'
2
-
3
- describe "Miscellaneous" do
4
- with_mongo
5
- old = Mongo.defaults[:generate_id] = false
6
- before do
7
- Mongo.defaults[:generate_id] = true
8
- class Tmp
9
- include Mongo::Object
10
- end
11
- end
12
- after do
13
- Mongo.defaults[:generate_id] = old
14
- remove_constants :Tmp
15
- end
16
-
17
- it "should use autogenerated random string id (if specified, instead of default BSON::ObjectId)" do
18
- o = Tmp.new
19
- db.objects.save o
20
- o._id.should be_a(String)
21
- o._id.size.should == Mongo.defaults[:random_string_id_size]
22
- end
23
-
24
- it "shoud convert to hash" do
25
- class Tmp
26
- attr_accessor :name
27
- end
28
- o = Tmp.new
29
- o.name = 'some name'
30
- o.to_hash.should == {name: 'some name', _class: 'Tmp'}
31
- end
32
- end