mongo_mapper-unstable 2010.2.28 → 2010.3.3

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
@@ -10,11 +10,11 @@ Jeweler::Tasks.new do |gem|
10
10
  gem.email = "nunemaker@gmail.com"
11
11
  gem.homepage = "http://github.com/jnunemaker/mongomapper"
12
12
  gem.authors = ["John Nunemaker"]
13
-
13
+
14
14
  gem.add_dependency('activesupport', '>= 2.3')
15
- gem.add_dependency('mongo', '0.18.3')
16
- gem.add_dependency('jnunemaker-validatable', '1.8.1')
17
-
15
+ gem.add_dependency('mongo', '0.19.1')
16
+ gem.add_dependency('jnunemaker-validatable', '1.8.3')
17
+
18
18
  gem.add_development_dependency('jnunemaker-matchy', '0.4.0')
19
19
  gem.add_development_dependency('shoulda', '2.10.2')
20
20
  gem.add_development_dependency('timecop', '0.3.1')
@@ -38,7 +38,7 @@ namespace :test do
38
38
  test.pattern = 'test/unit/**/test_*.rb'
39
39
  test.verbose = true
40
40
  end
41
-
41
+
42
42
  Rake::TestTask.new(:functionals) do |test|
43
43
  test.libs << 'test'
44
44
  test.ruby_opts << '-rubygems'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2010.02.28
1
+ 2010.03.03
@@ -17,10 +17,13 @@ module MongoMapper
17
17
  plugin Plugins::Keys
18
18
  plugin Plugins::Dirty # for now dirty needs to be after keys
19
19
  plugin Plugins::Logger
20
+ plugin Plugins::Modifiers
20
21
  plugin Plugins::Pagination
21
22
  plugin Plugins::Protected
22
23
  plugin Plugins::Rails
23
24
  plugin Plugins::Serialization
25
+ plugin Plugins::Timestamps
26
+ plugin Plugins::Userstamps
24
27
  plugin Plugins::Validations
25
28
  plugin Plugins::Callbacks # for now callbacks needs to be after validations
26
29
 
@@ -143,47 +146,6 @@ module MongoMapper
143
146
  find_each(options) { |document| document.destroy }
144
147
  end
145
148
 
146
- def increment(*args)
147
- modifier_update('$inc', args)
148
- end
149
-
150
- def decrement(*args)
151
- criteria, keys = criteria_and_keys_from_args(args)
152
- values, to_decrement = keys.values, {}
153
- keys.keys.each_with_index { |k, i| to_decrement[k] = -values[i].abs }
154
- collection.update(criteria, {'$inc' => to_decrement}, :multi => true)
155
- end
156
-
157
- def set(*args)
158
- modifier_update('$set', args)
159
- end
160
-
161
- def push(*args)
162
- modifier_update('$push', args)
163
- end
164
-
165
- def push_all(*args)
166
- modifier_update('$pushAll', args)
167
- end
168
-
169
- def push_uniq(*args)
170
- criteria, keys = criteria_and_keys_from_args(args)
171
- keys.each { |key, value | criteria[key] = {'$ne' => value} }
172
- collection.update(criteria, {'$push' => keys}, :multi => true)
173
- end
174
-
175
- def pull(*args)
176
- modifier_update('$pull', args)
177
- end
178
-
179
- def pull_all(*args)
180
- modifier_update('$pullAll', args)
181
- end
182
-
183
- def pop(*args)
184
- modifier_update('$pop', args)
185
- end
186
-
187
149
  def embeddable?
188
150
  false
189
151
  end
@@ -225,19 +187,6 @@ module MongoMapper
225
187
  database.collection(collection_name)
226
188
  end
227
189
 
228
- def timestamps!
229
- key :created_at, Time
230
- key :updated_at, Time
231
- class_eval { before_save :update_timestamps }
232
- end
233
-
234
- def userstamps!
235
- key :creator_id, ObjectId
236
- key :updater_id, ObjectId
237
- belongs_to :creator, :class_name => 'User'
238
- belongs_to :updater, :class_name => 'User'
239
- end
240
-
241
190
  def single_collection_inherited?
242
191
  keys.key?(:_type) && single_collection_inherited_superclass?
243
192
  end
@@ -258,18 +207,6 @@ module MongoMapper
258
207
  instances.size == 1 ? instances[0] : instances
259
208
  end
260
209
 
261
- def modifier_update(modifier, args)
262
- criteria, keys = criteria_and_keys_from_args(args)
263
- modifiers = {modifier => keys}
264
- collection.update(criteria, modifiers, :multi => true)
265
- end
266
-
267
- def criteria_and_keys_from_args(args)
268
- keys = args.pop
269
- criteria = args[0].is_a?(Hash) ? args[0] : {:id => args}
270
- [to_criteria(criteria), keys]
271
- end
272
-
273
210
  def assert_no_first_last_or_all(args)
274
211
  if args[0] == :first || args[0] == :last || args[0] == :all
275
212
  raise ArgumentError, "#{self}.find(:#{args}) is no longer supported, use #{self}.#{args} instead."
@@ -417,12 +354,6 @@ module MongoMapper
417
354
  @new = false
418
355
  collection.save(to_mongo, :safe => safe)
419
356
  end
420
-
421
- def update_timestamps
422
- now = Time.now.utc
423
- self[:created_at] = now if new? && !created_at?
424
- self[:updated_at] = now
425
- end
426
357
  end
427
358
  end # Document
428
359
  end # MongoMapper
@@ -13,7 +13,9 @@ module MongoMapper
13
13
  :before_validation, :after_validation,
14
14
  :before_validation_on_create, :after_validation_on_create,
15
15
  :before_validation_on_update, :after_validation_on_update,
16
- :before_destroy, :after_destroy
16
+ :before_destroy, :after_destroy,
17
+ :validate_on_create, :validate_on_update,
18
+ :validate
17
19
  )
18
20
  end
19
21
  end
@@ -48,16 +50,25 @@ module MongoMapper
48
50
  module InstanceMethods
49
51
  def valid?
50
52
  action = new? ? 'create' : 'update'
51
-
52
53
  run_callbacks(:before_validation)
53
54
  run_callbacks("before_validation_on_#{action}".to_sym)
54
55
  result = super
55
56
  run_callbacks("after_validation_on_#{action}".to_sym)
56
57
  run_callbacks(:after_validation)
57
-
58
58
  result
59
59
  end
60
60
 
61
+ # Overriding validatable's valid_for_group? to integrate validation callbacks
62
+ def valid_for_group?(group) #:nodoc:
63
+ errors.clear
64
+ run_before_validations
65
+ run_callbacks(:validate)
66
+ new? ? run_callbacks(:validate_on_create) : run_callbacks(:validate_on_update)
67
+ self.class.validate_children(self, group)
68
+ self.validate_group(group)
69
+ errors.empty?
70
+ end
71
+
61
72
  def destroy
62
73
  run_callbacks(:before_destroy)
63
74
  result = super
@@ -170,7 +170,7 @@ module MongoMapper
170
170
 
171
171
  def attributes=(attrs)
172
172
  return if attrs.blank?
173
-
173
+
174
174
  attrs.each_pair do |name, value|
175
175
  writer_method = "#{name}="
176
176
 
@@ -220,7 +220,7 @@ module MongoMapper
220
220
  def id
221
221
  _id
222
222
  end
223
-
223
+
224
224
  def id=(value)
225
225
  if self.class.using_object_id?
226
226
  value = MongoMapper.normalize_object_id(value)
@@ -262,7 +262,7 @@ module MongoMapper
262
262
  def assign_type_if_present
263
263
  self._type = self.class.name if respond_to?(:_type=)
264
264
  end
265
-
265
+
266
266
  def ensure_key_exists(name)
267
267
  self.class.key(name) unless respond_to?("#{name}=")
268
268
  end
@@ -283,11 +283,16 @@ module MongoMapper
283
283
 
284
284
  def write_key(name, value)
285
285
  key = keys[name]
286
+
287
+ if key.embeddable? && value.is_a?(key.type)
288
+ value._parent_document = self
289
+ end
290
+
286
291
  instance_variable_set "@#{name}_before_typecast", value
287
292
  instance_variable_set "@#{name}", key.set(value)
288
293
  end
289
294
  end
290
-
295
+
291
296
  class Key
292
297
  attr_accessor :name, :type, :options, :default_value
293
298
 
@@ -0,0 +1,87 @@
1
+ module MongoMapper
2
+ module Plugins
3
+ module Modifiers
4
+ module ClassMethods
5
+ def increment(*args)
6
+ modifier_update('$inc', args)
7
+ end
8
+
9
+ def decrement(*args)
10
+ criteria, keys = criteria_and_keys_from_args(args)
11
+ values, to_decrement = keys.values, {}
12
+ keys.keys.each_with_index { |k, i| to_decrement[k] = -values[i].abs }
13
+ collection.update(criteria, {'$inc' => to_decrement}, :multi => true)
14
+ end
15
+
16
+ def set(*args)
17
+ modifier_update('$set', args)
18
+ end
19
+
20
+ def push(*args)
21
+ modifier_update('$push', args)
22
+ end
23
+
24
+ def push_all(*args)
25
+ modifier_update('$pushAll', args)
26
+ end
27
+
28
+ def push_uniq(*args)
29
+ criteria, keys = criteria_and_keys_from_args(args)
30
+ keys.each { |key, value | criteria[key] = {'$ne' => value} }
31
+ collection.update(criteria, {'$push' => keys}, :multi => true)
32
+ end
33
+
34
+ def pull(*args)
35
+ modifier_update('$pull', args)
36
+ end
37
+
38
+ def pull_all(*args)
39
+ modifier_update('$pullAll', args)
40
+ end
41
+
42
+ def pop(*args)
43
+ modifier_update('$pop', args)
44
+ end
45
+
46
+ private
47
+ def modifier_update(modifier, args)
48
+ criteria, keys = criteria_and_keys_from_args(args)
49
+ modifiers = {modifier => keys}
50
+ collection.update(criteria, modifiers, :multi => true)
51
+ end
52
+
53
+ def criteria_and_keys_from_args(args)
54
+ keys = args.pop
55
+ criteria = args[0].is_a?(Hash) ? args[0] : {:id => args}
56
+ [to_criteria(criteria), keys]
57
+ end
58
+ end
59
+
60
+ module InstanceMethods
61
+ def increment(hash)
62
+ self.class.increment({:_id => id}, hash)
63
+ end
64
+
65
+ def decrement(hash)
66
+ self.class.decrement({:_id => id}, hash)
67
+ end
68
+
69
+ def set(hash)
70
+ self.class.set({:_id => id}, hash)
71
+ end
72
+
73
+ def push(hash)
74
+ self.class.push({:_id => id}, hash)
75
+ end
76
+
77
+ def pull(hash)
78
+ self.class.pull({:_id => id}, hash)
79
+ end
80
+
81
+ def push_uniq(hash)
82
+ self.class.push_uniq({:_id => id}, hash)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -1,41 +1,49 @@
1
1
  module MongoMapper
2
2
  module Plugins
3
3
  module Rails
4
+ def self.configure(model)
5
+ model.extend ActiveModel::Naming if defined?(ActiveModel)
6
+ end
7
+
4
8
  module InstanceMethods
5
9
  def to_param
6
10
  id.to_s
7
11
  end
8
-
12
+
13
+ def to_model
14
+ self
15
+ end
16
+
9
17
  def new_record?
10
18
  new?
11
19
  end
12
-
20
+
13
21
  def read_attribute(name)
14
22
  self[name]
15
23
  end
16
-
24
+
17
25
  def read_attribute_before_typecast(name)
18
26
  read_key_before_typecast(name)
19
27
  end
20
-
28
+
21
29
  def write_attribute(name, value)
22
30
  self[name] = value
23
31
  end
24
32
  end
25
-
33
+
26
34
  module ClassMethods
27
35
  def has_one(*args)
28
36
  one(*args)
29
37
  end
30
-
38
+
31
39
  def has_many(*args)
32
40
  many(*args)
33
41
  end
34
-
42
+
35
43
  def column_names
36
44
  keys.keys
37
45
  end
38
-
46
+
39
47
  def human_name
40
48
  self.name.demodulize.titleize
41
49
  end
@@ -4,102 +4,72 @@ module MongoMapper
4
4
  module Plugins
5
5
  module Serialization
6
6
  def self.configure(model)
7
- model.class_eval { include Json }
7
+ model.class_eval { cattr_accessor :include_root_in_json, :instance_writer => true }
8
8
  end
9
9
 
10
- class Serializer
11
- attr_reader :options
12
-
13
- def initialize(record, options={})
14
- @record, @options = record, options.dup
15
- end
16
-
17
- def serializable_key_names
18
- key_names = @record.attributes.keys
19
-
20
- if options[:only]
21
- options.delete(:except)
22
- key_names = key_names & Array(options[:only]).collect { |n| n.to_s }
23
- else
24
- options[:except] = Array(options[:except])
25
- key_names = key_names - options[:except].collect { |n| n.to_s }
26
- end
27
-
28
- key_names
29
- end
30
-
31
- def serializable_method_names
32
- Array(options[:methods]).inject([]) do |method_attributes, name|
33
- method_attributes << name if @record.respond_to?(name.to_s)
34
- method_attributes
10
+ module InstanceMethods
11
+ def as_json options={}
12
+ options ||= {}
13
+ unless options[:only]
14
+ methods = [options.delete(:methods)].flatten.compact
15
+ methods << :id
16
+ options[:methods] = methods.uniq
35
17
  end
36
- end
37
18
 
38
- def serializable_names
39
- serializable_key_names + serializable_method_names
40
- end
19
+ except = [options.delete(:except)].flatten.compact
20
+ except << :_id
21
+ options[:except] = except
41
22
 
42
- def serializable_record
43
- returning(serializable_record = {}) do
44
- serializable_names.each { |name| serializable_record[name] = @record.send(name) }
45
- end
46
- end
23
+ # Direct rip from Rails 3 ActiveModel Serialization (#serializable_hash)
24
+ hash = begin
25
+ options[:only] = Array.wrap(options[:only]).map { |n| n.to_s }
26
+ options[:except] = Array.wrap(options[:except]).map { |n| n.to_s }
47
27
 
48
- def serialize
49
- # overwrite to implement
50
- end
28
+ attribute_names = attributes.keys.sort
29
+ if options[:only].any?
30
+ attribute_names &= options[:only]
31
+ elsif options[:except].any?
32
+ attribute_names -= options[:except]
33
+ end
51
34
 
52
- def to_s(&block)
53
- serialize(&block)
54
- end
55
- end
56
-
57
- module Json
58
- def self.included(base)
59
- base.cattr_accessor :include_root_in_json, :instance_writer => false
60
- base.extend ClassMethods
61
- end
35
+ method_names = Array.wrap(options[:methods]).inject([]) do |methods, name|
36
+ methods << name if respond_to?(name.to_s)
37
+ methods
38
+ end
62
39
 
63
- module ClassMethods
64
- def json_class_name
65
- @json_class_name ||= name.demodulize.underscore.inspect
40
+ (attribute_names + method_names).inject({}) { |hash, name|
41
+ hash[name] = send(name)
42
+ hash
43
+ }
66
44
  end
67
- end
68
-
69
- def to_json(options={})
70
- apply_to_json_defaults(options)
71
-
72
- if include_root_in_json
73
- "{#{self.class.json_class_name}: #{JsonSerializer.new(self, options).to_s}}"
74
- else
75
- JsonSerializer.new(self, options).to_s
45
+ # End rip
46
+
47
+ options.delete(:only) if options[:only].nil? or options[:only].empty?
48
+
49
+ hash.each do |key, value|
50
+ if value.is_a?(Array)
51
+ hash[key] = value.map do |item|
52
+ item.respond_to?(:as_json) ? item.as_json(options) : item
53
+ end
54
+ elsif value.is_a? Mongo::ObjectID
55
+ hash[key] = value.to_s
56
+ elsif value.respond_to?(:as_json)
57
+ hash[key] = value.as_json(options)
58
+ end
76
59
  end
60
+
61
+ # Replicate Rails 3 naming - and also bin anytihng after : for use in our dynamic classes from unit tests
62
+ hash = { ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)).gsub(/:.*/,'') => hash } if include_root_in_json
63
+ hash
77
64
  end
65
+ end
78
66
 
67
+ module ClassMethods
79
68
  def from_json(json)
80
- self.attributes = ActiveSupport::JSON.decode(json)
81
- self
69
+ self.new(ActiveSupport::JSON.decode(json))
82
70
  end
83
-
84
- class JsonSerializer < Serializer
85
- def serialize
86
- serializable_record.to_json
87
- end
88
- end
89
-
90
- private
91
- def apply_to_json_defaults(options)
92
- unless options[:only]
93
- methods = [options.delete(:methods)].flatten.compact
94
- methods << :id
95
- options[:methods] = methods.uniq
96
- end
97
-
98
- except = [options.delete(:except)].flatten.compact
99
- except << :_id
100
- options[:except] = except
101
- end
102
71
  end
72
+
103
73
  end
104
74
  end
105
75
  end
@@ -0,0 +1,21 @@
1
+ module MongoMapper
2
+ module Plugins
3
+ module Timestamps
4
+ module ClassMethods
5
+ def timestamps!
6
+ key :created_at, Time
7
+ key :updated_at, Time
8
+ class_eval { before_save :update_timestamps }
9
+ end
10
+ end
11
+
12
+ module InstanceMethods
13
+ def update_timestamps
14
+ now = Time.now.utc
15
+ self[:created_at] = now if new? && !created_at?
16
+ self[:updated_at] = now
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,14 @@
1
+ module MongoMapper
2
+ module Plugins
3
+ module Userstamps
4
+ module ClassMethods
5
+ def userstamps!
6
+ key :creator_id, ObjectId
7
+ key :updater_id, ObjectId
8
+ belongs_to :creator, :class_name => 'User'
9
+ belongs_to :updater, :class_name => 'User'
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -20,9 +20,12 @@ module MongoMapper
20
20
  autoload :Inspect, 'mongo_mapper/plugins/inspect'
21
21
  autoload :Keys, 'mongo_mapper/plugins/keys'
22
22
  autoload :Logger, 'mongo_mapper/plugins/logger'
23
+ autoload :Modifiers, 'mongo_mapper/plugins/modifiers'
23
24
  autoload :Protected, 'mongo_mapper/plugins/protected'
24
25
  autoload :Rails, 'mongo_mapper/plugins/rails'
25
26
  autoload :Serialization, 'mongo_mapper/plugins/serialization'
27
+ autoload :Timestamps, 'mongo_mapper/plugins/timestamps'
28
+ autoload :Userstamps, 'mongo_mapper/plugins/userstamps'
26
29
  autoload :Validations, 'mongo_mapper/plugins/validations'
27
30
  end
28
31
  end
data/lib/mongo_mapper.rb CHANGED
@@ -7,8 +7,8 @@ require 'uri'
7
7
  # if there is a better way to do this, please enlighten me!
8
8
  if self.class.const_defined?(:Gem)
9
9
  gem 'activesupport', '>= 2.3'
10
- gem 'mongo', '0.18.3'
11
- gem 'jnunemaker-validatable', '1.8.1'
10
+ gem 'mongo', '0.19.1'
11
+ gem 'jnunemaker-validatable', '1.8.3'
12
12
  end
13
13
 
14
14
  require 'active_support/all'
@@ -0,0 +1,11 @@
1
+ require 'test_helper'
2
+ require 'active_model'
3
+ require 'models'
4
+
5
+ class ActiveModelLintTest < ActiveModel::TestCase
6
+ include ActiveModel::Lint::Tests
7
+
8
+ def setup
9
+ @model = Post.new
10
+ end
11
+ end