mongodb 2.0.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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