mongoo 0.4.5 → 0.4.6

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.5
1
+ 0.4.6
@@ -52,6 +52,10 @@ require "mongoo/attribute_proxy"
52
52
  require "mongoo/changelog"
53
53
  require "mongoo/persistence"
54
54
  require "mongoo/modifiers"
55
+ require "mongoo/core"
55
56
  require "mongoo/base"
57
+ require "mongoo/embedded/base"
58
+ require "mongoo/embedded/array_proxy"
59
+ require "mongoo/embedded/hash_proxy"
56
60
  require "mongoo/mongohash"
57
61
  require "mongoo/identity_map"
@@ -1,194 +1,25 @@
1
1
  module Mongoo
2
- class UnknownAttributeError < Exception; end
3
-
4
- class Base
2
+ class Base < Mongoo::Core
5
3
 
6
4
  include Mongoo::Changelog
7
5
  include Mongoo::Persistence
8
6
  include Mongoo::Modifiers
9
7
 
10
- include ActiveModel::Validations
11
-
12
8
  extend ActiveModel::Callbacks
13
- extend ActiveModel::Naming
14
9
 
15
10
  define_model_callbacks :insert, :update, :remove
16
11
 
17
- def self.attribute(name, opts={})
18
- raise ArgumentError.new("missing :type") unless opts[:type]
19
- self.attributes[name.to_s] = opts
20
- define_attribute_methods
21
- true
22
- end
23
-
24
- def self.attributes
25
- Mongoo::ATTRIBUTE_META[self.to_s] ||= {}
26
- end
27
-
28
- def self.attributes_tree
29
- tree = {}
30
- self.attributes.each do |name, opts|
31
- parts = name.split(".")
32
- curr_branch = tree
33
- while part = parts.shift
34
- if !parts.empty?
35
- curr_branch[part.to_s] ||= {}
36
- curr_branch = curr_branch[part.to_s]
37
- else
38
- curr_branch[part.to_s] = opts[:type]
39
- end
40
- end
41
- end
42
- tree
43
- end
44
-
45
- def self.define_attribute_methods
46
- define_method("id") do
47
- get("_id")
48
- end
49
- define_method("id=") do |val|
50
- set("_id", val)
51
- end
52
-
53
- self.attributes_tree.each do |name, val|
54
- if val.is_a?(Hash)
55
- define_method(name) do
56
- AttributeProxy.new(val, [name], self)
57
- end
58
- else
59
- define_method(name) do
60
- get(name)
61
- end
62
- define_method("#{name}=") do |val|
63
- set(name, val)
64
- end
65
- end
66
- end
67
- end
68
-
69
- def self.known_attribute?(k)
70
- k == "_id" || self.attributes[k.to_s]
71
- end
72
-
73
- def initialize(hash={}, persisted=false)
74
- @persisted = persisted
75
- init_from_hash(hash)
76
- set_persisted_mongohash((persisted? ? mongohash : nil))
77
- end
78
-
79
- def ==(val)
80
- if val.class.to_s == self.class.to_s
81
- if val.persisted?
82
- val.id == self.id
83
- else
84
- self.mongohash.raw_hash == val.mongohash.raw_hash
85
- end
86
- end
87
- end
88
-
89
- def known_attribute?(k)
90
- self.class.known_attribute?(k)
91
- end
92
-
93
- def read_attribute_for_validation(key)
94
- get_attribute(key)
95
- end
96
-
97
- def get_attribute(k)
98
- unless known_attribute?(k)
99
- raise UnknownAttributeError, k
100
- end
101
- mongohash.dot_get(k.to_s)
102
- end
103
- alias :get :get_attribute
104
- alias :g :get_attribute
105
-
106
- def set_attribute(k,v)
107
- unless known_attribute?(k)
108
- if self.respond_to?("#{k}=")
109
- return self.send("#{k}=", v)
110
- else
111
- raise UnknownAttributeError, k
112
- end
113
- end
114
- unless k.to_s == "_id" || v.nil?
115
- field_type = self.class.attributes[k.to_s][:type]
116
- v = Mongoo::AttributeSanitizer.sanitize(field_type, v)
117
- end
118
- mongohash.dot_set(k.to_s,v)
119
- end
120
- alias :set :set_attribute
121
- alias :s :set_attribute
122
-
123
- def unset_attribute(k)
124
- mongohash.dot_delete(k); true
125
- end
126
- alias :unset :unset_attribute
127
- alias :u :unset_attribute
128
-
129
- def set_attributes(k_v_pairs)
130
- k_v_pairs.each do |k,v|
131
- set_attribute(k,v)
132
- end
133
- end
134
- alias :sets :set_attributes
135
-
136
- def get_attributes(keys)
137
- found = {}
138
- keys.each { |k| found[k.to_s] = get_attribute(k) }
139
- found
140
- end
141
- alias :gets :get_attributes
142
-
143
- def unset_attributes(keys)
144
- keys.each { |k| unset_attribute(k) }; true
145
- end
146
- alias :unsets :unset_attributes
147
-
148
- def attributes
149
- mongohash.to_key_value
150
- end
151
-
152
- def merge!(hash)
153
- if hash.is_a?(Mongoo::Mongohash)
154
- hash = hash.raw_hash
155
- end
156
- hash.deep_stringify_keys!
157
- hash = mongohash.raw_hash.deep_merge(hash)
158
- set_mongohash( Mongoo::Mongohash.new(hash) )
159
- mongohash
12
+ def embedded_array_proxy(attrib, klass)
13
+ Mongoo::Embedded::ArrayProxy.new(self, attrib, klass)
160
14
  end
161
15
 
162
- def init_from_hash(hash)
163
- unless hash.is_a?(Mongoo::Mongohash)
164
- hash = Mongoo::Mongohash.new(hash)
165
- end
166
- set_mongohash hash
16
+ def embedded_hash_proxy(attrib, klass)
17
+ Mongoo::Embedded::HashProxy.new(self, attrib, klass)
167
18
  end
168
- protected :init_from_hash
169
19
 
170
- def set_mongohash(mongohash)
171
- @mongohash = mongohash
20
+ def embedded_doc(attrib, klass)
21
+ klass.new(self, attrib)
172
22
  end
173
- protected :set_mongohash
174
23
 
175
- def mongohash
176
- @mongohash
177
- end
178
-
179
- def set_persisted_mongohash(hash)
180
- @serialized_persisted_mongohash = Marshal.dump(hash)
181
- @persisted_mongohash = nil
182
- true
183
- end
184
- protected :set_persisted_mongohash
185
-
186
- def persisted_mongohash
187
- @persisted_mongohash ||= begin
188
- if @serialized_persisted_mongohash
189
- Marshal.load(@serialized_persisted_mongohash)
190
- end
191
- end
192
- end
193
24
  end
194
25
  end
@@ -0,0 +1,190 @@
1
+ module Mongoo
2
+ class UnknownAttributeError < Exception; end
3
+
4
+ class Core
5
+ include ActiveModel::Validations
6
+ extend ActiveModel::Naming
7
+
8
+ def self.attribute(name, opts={})
9
+ raise ArgumentError.new("missing :type") unless opts[:type]
10
+ self.attributes[name.to_s] = opts
11
+ define_attribute_methods
12
+ true
13
+ end
14
+
15
+ def self.attributes
16
+ Mongoo::ATTRIBUTE_META[self.to_s] ||= {}
17
+ end
18
+
19
+ def self.attributes_tree
20
+ tree = {}
21
+ self.attributes.each do |name, opts|
22
+ parts = name.split(".")
23
+ curr_branch = tree
24
+ while part = parts.shift
25
+ if !parts.empty?
26
+ curr_branch[part.to_s] ||= {}
27
+ curr_branch = curr_branch[part.to_s]
28
+ else
29
+ curr_branch[part.to_s] = opts[:type]
30
+ end
31
+ end
32
+ end
33
+ tree
34
+ end
35
+
36
+ def self.define_attribute_methods
37
+ define_method("id") do
38
+ get("_id")
39
+ end
40
+ define_method("id=") do |val|
41
+ set("_id", val)
42
+ end
43
+
44
+ self.attributes_tree.each do |name, val|
45
+ if val.is_a?(Hash)
46
+ define_method(name) do
47
+ AttributeProxy.new(val, [name], self)
48
+ end
49
+ else
50
+ define_method(name) do
51
+ get(name)
52
+ end
53
+ define_method("#{name}=") do |val|
54
+ set(name, val)
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ def self.known_attribute?(k)
61
+ k == "_id" || self.attributes[k.to_s]
62
+ end
63
+
64
+ def initialize(hash={}, persisted=false)
65
+ @persisted = persisted
66
+ init_from_hash(hash)
67
+ set_persisted_mongohash((persisted? ? mongohash : nil))
68
+ end
69
+
70
+ def ==(val)
71
+ if val.class.to_s == self.class.to_s
72
+ if val.persisted?
73
+ val.id == self.id
74
+ else
75
+ self.mongohash.raw_hash == val.mongohash.raw_hash
76
+ end
77
+ end
78
+ end
79
+
80
+ def known_attribute?(k)
81
+ self.class.known_attribute?(k)
82
+ end
83
+
84
+ def read_attribute_for_validation(key)
85
+ get_attribute(key)
86
+ end
87
+
88
+ def get_attribute(k)
89
+ unless known_attribute?(k)
90
+ raise UnknownAttributeError, k
91
+ end
92
+ mongohash.dot_get(k.to_s)
93
+ end
94
+ alias :get :get_attribute
95
+ alias :g :get_attribute
96
+
97
+ def set_attribute(k,v)
98
+ unless known_attribute?(k)
99
+ if self.respond_to?("#{k}=")
100
+ self.send("#{k}=", v)
101
+ return v
102
+ else
103
+ raise UnknownAttributeError, k
104
+ end
105
+ end
106
+ unless k.to_s == "_id" || v.nil?
107
+ field_type = self.class.attributes[k.to_s][:type]
108
+ v = Mongoo::AttributeSanitizer.sanitize(field_type, v)
109
+ end
110
+ mongohash.dot_set(k.to_s,v); v
111
+ end
112
+ alias :set :set_attribute
113
+ alias :s :set_attribute
114
+
115
+ def unset_attribute(k)
116
+ mongohash.dot_delete(k); true
117
+ end
118
+ alias :unset :unset_attribute
119
+ alias :u :unset_attribute
120
+
121
+ def set_attributes(k_v_pairs)
122
+ k_v_pairs.each do |k,v|
123
+ set_attribute(k,v)
124
+ end
125
+ end
126
+ alias :sets :set_attributes
127
+
128
+ def get_attributes(keys)
129
+ found = {}
130
+ keys.each { |k| found[k.to_s] = get_attribute(k) }
131
+ found
132
+ end
133
+ alias :gets :get_attributes
134
+
135
+ def unset_attributes(keys)
136
+ keys.each { |k| unset_attribute(k) }; true
137
+ end
138
+ alias :unsets :unset_attributes
139
+
140
+ def attributes
141
+ mongohash.to_key_value
142
+ end
143
+
144
+ def merge!(hash)
145
+ if hash.is_a?(Mongoo::Mongohash)
146
+ hash = hash.raw_hash
147
+ end
148
+ hash.deep_stringify_keys!
149
+ hash = mongohash.raw_hash.deep_merge(hash)
150
+ set_mongohash( Mongoo::Mongohash.new(hash) )
151
+ mongohash
152
+ end
153
+
154
+ def init_from_hash(hash)
155
+ unless hash.is_a?(Mongoo::Mongohash)
156
+ hash = Mongoo::Mongohash.new(hash)
157
+ end
158
+ set_mongohash hash
159
+ end
160
+ protected :init_from_hash
161
+
162
+ def set_mongohash(mongohash)
163
+ @mongohash = mongohash
164
+ end
165
+ protected :set_mongohash
166
+
167
+ def mongohash
168
+ @mongohash
169
+ end
170
+
171
+ def set_persisted_mongohash(hash)
172
+ @serialized_persisted_mongohash = Marshal.dump(hash)
173
+ @persisted_mongohash = nil
174
+ true
175
+ end
176
+ protected :set_persisted_mongohash
177
+
178
+ def persisted_mongohash
179
+ @persisted_mongohash ||= begin
180
+ if @serialized_persisted_mongohash
181
+ Marshal.load(@serialized_persisted_mongohash)
182
+ end
183
+ end
184
+ end
185
+
186
+ def to_hash
187
+ mongohash.to_hash
188
+ end
189
+ end # Core
190
+ end # Mongoo
@@ -0,0 +1,45 @@
1
+ module Mongoo
2
+ module Embedded
3
+ class ArrayProxy
4
+
5
+ def initialize(doc, array, klass)
6
+ @doc = doc
7
+ @array = array
8
+ @klass = klass
9
+ end
10
+
11
+ def build(hash)
12
+ @klass.new(@doc,hash)
13
+ end
14
+
15
+ def raw
16
+ @array
17
+ end
18
+
19
+ def range(min=0, max=-1)
20
+ raw[min..max].collect { |h| build(h) }
21
+ end
22
+
23
+ def all
24
+ range
25
+ end
26
+
27
+ def each
28
+ raw.each { |h| yield(build(h)) }
29
+ end
30
+
31
+ def push(o)
32
+ raw << o.to_hash
33
+ end
34
+
35
+ def pop(o)
36
+ raw.pop o.to_hash
37
+ end
38
+
39
+ def size
40
+ raw.size
41
+ end
42
+
43
+ end # ArrayProxy
44
+ end # Embedded
45
+ end # Mongoo
@@ -0,0 +1,21 @@
1
+ module Mongoo
2
+ module Embedded
3
+ class Base < Mongoo::Core
4
+
5
+ def initialize(parent, hash={})
6
+ @parent = parent
7
+ @persisted = persisted?
8
+ init_from_hash(hash)
9
+ end
10
+
11
+ def persisted?
12
+ @parent.persisted?
13
+ end
14
+
15
+ def ==(other)
16
+ to_hash == other.to_hash
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,41 @@
1
+ module Mongoo
2
+ module Embedded
3
+ class HashProxy
4
+
5
+ def initialize(doc, hash, klass)
6
+ @doc = doc
7
+ @hash = hash
8
+ @klass = klass
9
+ end
10
+
11
+ def build(hash)
12
+ @klass.new(@doc,hash)
13
+ end
14
+
15
+ def raw
16
+ @hash
17
+ end
18
+
19
+ def [](k)
20
+ build raw[k]
21
+ end
22
+
23
+ def []=(k,o)
24
+ raw[k] = o.to_hash
25
+ end
26
+
27
+ def each
28
+ raw.each { |k,v| yield(k, build(v)) }
29
+ end
30
+
31
+ def size
32
+ raw.size
33
+ end
34
+
35
+ def keys
36
+ raw.keys
37
+ end
38
+
39
+ end # HashProxy
40
+ end # Embedded
41
+ end # Mongoo
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mongoo}
8
- s.version = "0.4.5"
8
+ s.version = "0.4.6"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Ben Myles"]
12
- s.date = %q{2011-06-06}
12
+ s.date = %q{2011-06-07}
13
13
  s.description = %q{Simple object mapper for MongoDB}
14
14
  s.email = %q{ben.myles@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -30,7 +30,11 @@ Gem::Specification.new do |s|
30
30
  "lib/mongoo/attribute_sanitizer.rb",
31
31
  "lib/mongoo/base.rb",
32
32
  "lib/mongoo/changelog.rb",
33
+ "lib/mongoo/core.rb",
33
34
  "lib/mongoo/cursor.rb",
35
+ "lib/mongoo/embedded/array_proxy.rb",
36
+ "lib/mongoo/embedded/base.rb",
37
+ "lib/mongoo/embedded/hash_proxy.rb",
34
38
  "lib/mongoo/hash_ext.rb",
35
39
  "lib/mongoo/identity_map.rb",
36
40
  "lib/mongoo/modifiers.rb",
@@ -39,6 +43,7 @@ Gem::Specification.new do |s|
39
43
  "mongoo.gemspec",
40
44
  "test/helper.rb",
41
45
  "test/test_activemodel.rb",
46
+ "test/test_embedded.rb",
42
47
  "test/test_identity_map.rb",
43
48
  "test/test_mongohash.rb",
44
49
  "test/test_mongoo.rb",
@@ -52,6 +57,7 @@ Gem::Specification.new do |s|
52
57
  s.test_files = [
53
58
  "test/helper.rb",
54
59
  "test/test_activemodel.rb",
60
+ "test/test_embedded.rb",
55
61
  "test/test_identity_map.rb",
56
62
  "test/test_mongohash.rb",
57
63
  "test/test_mongoo.rb",
@@ -0,0 +1,86 @@
1
+ require 'helper'
2
+
3
+ class Book < Mongoo::Base
4
+ attribute "title", :type => :string
5
+ attribute "chapters", :type => :array
6
+ attribute "authors", :type => :hash
7
+ attribute "sample_chapter", :type => :hash
8
+
9
+ def chapters
10
+ @chapters ||= embedded_array_proxy((g('chapters') || s('chapters',[])), Book::Chapter)
11
+ end
12
+
13
+ def authors
14
+ @authors ||= embedded_hash_proxy((g('authors') || s('authors', {})), Book::Author)
15
+ end
16
+
17
+ def sample_chapter
18
+ @sample_chapter ||= embedded_doc((g('sample_chapter') || s('sample_chapter', {})), Book::Chapter)
19
+ end
20
+ end
21
+
22
+ class Book::Chapter < Mongoo::Embedded::Base
23
+ attribute "title", :type => :string
24
+ end
25
+
26
+ class Book::Author < Mongoo::Embedded::Base
27
+ attribute "first_name", :type => :string
28
+ attribute "last_name", :type => :string
29
+ end
30
+
31
+ class TestEmbedded < Test::Unit::TestCase
32
+ def setup
33
+ Book.collection.drop
34
+ end
35
+
36
+ should "be able to work with embedded doc arrays" do
37
+ b = Book.new
38
+ b.title = "Skydiving Instruction Manual"
39
+
40
+ b.chapters.push(b.chapters.build(title: "How to Land"))
41
+
42
+ b2 = Book.new(title: "Something Else")
43
+ b2.chapters.push b2.chapters.build(title: "How to Transcend Fear")
44
+
45
+ assert_equal [], b.chapters.raw & b2.chapters.raw
46
+
47
+ b2.chapters.push b2.chapters.build({title: "How to Land"})
48
+
49
+ assert_equal([{"title"=>"How to Land"}], b.chapters.raw & b2.chapters.raw)
50
+
51
+ assert_equal b.chapters.range(0,0), b2.chapters.range(1,1)
52
+ assert_not_equal b.chapters.range(0,0), b2.chapters.range(0,0)
53
+
54
+ assert_equal 2, b2.chapters.size
55
+ end
56
+
57
+ should "be able to work with embedded doc hashes" do
58
+ b = Book.new
59
+ b.authors["primary"] = b.authors.build(first_name: "Ben", last_name: "Myles")
60
+ b.authors["secondary"] = b.authors.build(first_name: "John", last_name: "Smith")
61
+
62
+ assert_equal "Ben", b.authors["primary"].first_name
63
+ assert_equal "Smith", b.authors["secondary"].last_name
64
+
65
+ assert_equal 2, b.authors.size
66
+ assert_equal ["primary", "secondary"], b.authors.keys
67
+
68
+ b.insert!
69
+
70
+ b = Book.find_one(b.id)
71
+
72
+ assert_equal "Ben", b.authors["primary"].first_name
73
+ assert_equal 2, b.authors.size
74
+ assert_equal ["primary", "secondary"], b.authors.keys
75
+ end
76
+
77
+ should "be able to work with a single embedded doc" do
78
+ b = Book.new(title: "BASE Jumping Basics")
79
+ b.sample_chapter.title = "Understanding the Risks"
80
+ assert_equal "Understanding the Risks", b.g('sample_chapter')['title']
81
+ b.insert!
82
+ b = Book.find_one(b.id)
83
+ assert_equal "Understanding the Risks", b.sample_chapter.title
84
+ assert_equal "Understanding the Risks", b.g('sample_chapter')['title']
85
+ end
86
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: mongoo
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.4.5
5
+ version: 0.4.6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Ben Myles
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-06-06 00:00:00 -07:00
13
+ date: 2011-06-07 00:00:00 -07:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -157,7 +157,11 @@ files:
157
157
  - lib/mongoo/attribute_sanitizer.rb
158
158
  - lib/mongoo/base.rb
159
159
  - lib/mongoo/changelog.rb
160
+ - lib/mongoo/core.rb
160
161
  - lib/mongoo/cursor.rb
162
+ - lib/mongoo/embedded/array_proxy.rb
163
+ - lib/mongoo/embedded/base.rb
164
+ - lib/mongoo/embedded/hash_proxy.rb
161
165
  - lib/mongoo/hash_ext.rb
162
166
  - lib/mongoo/identity_map.rb
163
167
  - lib/mongoo/modifiers.rb
@@ -166,6 +170,7 @@ files:
166
170
  - mongoo.gemspec
167
171
  - test/helper.rb
168
172
  - test/test_activemodel.rb
173
+ - test/test_embedded.rb
169
174
  - test/test_identity_map.rb
170
175
  - test/test_mongohash.rb
171
176
  - test/test_mongoo.rb
@@ -184,7 +189,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
184
189
  requirements:
185
190
  - - ">="
186
191
  - !ruby/object:Gem::Version
187
- hash: 728381716729290434
192
+ hash: -2643579001889888610
188
193
  segments:
189
194
  - 0
190
195
  version: "0"
@@ -204,6 +209,7 @@ summary: Object mapper for MongoDB
204
209
  test_files:
205
210
  - test/helper.rb
206
211
  - test/test_activemodel.rb
212
+ - test/test_embedded.rb
207
213
  - test/test_identity_map.rb
208
214
  - test/test_mongohash.rb
209
215
  - test/test_mongoo.rb