mongoo 0.4.5 → 0.4.6

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