mongo_mapper-unstable 2010.1.6 → 2010.1.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/VERSION +1 -1
  2. data/lib/mongo_mapper/descendant_appends.rb +44 -0
  3. data/lib/mongo_mapper/document.rb +54 -98
  4. data/lib/mongo_mapper/embedded_document.rb +28 -348
  5. data/lib/mongo_mapper/finder_options.rb +15 -33
  6. data/lib/mongo_mapper/plugins/associations/base.rb +121 -0
  7. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +28 -0
  8. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +23 -0
  9. data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
  10. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +49 -0
  11. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +139 -0
  12. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  13. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +117 -0
  14. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
  15. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
  16. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
  17. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +66 -0
  18. data/lib/mongo_mapper/plugins/associations/proxy.rb +118 -0
  19. data/lib/mongo_mapper/plugins/associations.rb +104 -0
  20. data/lib/mongo_mapper/plugins/callbacks.rb +65 -0
  21. data/lib/mongo_mapper/plugins/clone.rb +13 -0
  22. data/lib/mongo_mapper/plugins/descendants.rb +16 -0
  23. data/lib/mongo_mapper/plugins/dirty.rb +119 -0
  24. data/lib/mongo_mapper/plugins/equality.rb +11 -0
  25. data/lib/mongo_mapper/plugins/identity_map.rb +66 -0
  26. data/lib/mongo_mapper/plugins/inspect.rb +14 -0
  27. data/lib/mongo_mapper/plugins/keys.rb +295 -0
  28. data/lib/mongo_mapper/plugins/logger.rb +17 -0
  29. data/lib/mongo_mapper/plugins/pagination.rb +85 -0
  30. data/lib/mongo_mapper/plugins/rails.rb +45 -0
  31. data/lib/mongo_mapper/plugins/serialization.rb +109 -0
  32. data/lib/mongo_mapper/plugins/validations.rb +48 -0
  33. data/lib/mongo_mapper/plugins.rb +19 -0
  34. data/lib/mongo_mapper/support.rb +36 -15
  35. data/lib/mongo_mapper.rb +23 -22
  36. data/performance/read_write.rb +52 -0
  37. data/specs.watchr +23 -2
  38. data/test/functional/associations/test_belongs_to_proxy.rb +1 -1
  39. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +58 -39
  40. data/test/functional/associations/test_many_embedded_proxy.rb +103 -69
  41. data/test/functional/test_dirty.rb +1 -1
  42. data/test/functional/test_document.rb +25 -25
  43. data/test/functional/test_embedded_document.rb +66 -63
  44. data/test/functional/test_identity_map.rb +233 -0
  45. data/test/functional/test_modifiers.rb +14 -0
  46. data/test/functional/test_string_id_compatibility.rb +4 -4
  47. data/test/functional/test_validations.rb +13 -0
  48. data/test/models.rb +0 -39
  49. data/test/test_helper.rb +8 -2
  50. data/test/unit/associations/test_base.rb +1 -1
  51. data/test/unit/associations/test_proxy.rb +3 -3
  52. data/test/unit/test_descendant_appends.rb +71 -0
  53. data/test/unit/test_document.rb +35 -46
  54. data/test/unit/test_embedded_document.rb +218 -271
  55. data/test/unit/{test_key.rb → test_keys.rb} +0 -0
  56. data/test/unit/test_pagination.rb +10 -2
  57. data/test/unit/test_plugins.rb +42 -0
  58. data/test/unit/test_rails.rb +123 -0
  59. data/test/unit/{test_serializations.rb → test_serialization.rb} +0 -0
  60. data/test/unit/test_support.rb +10 -6
  61. data/test/unit/test_time_zones.rb +2 -2
  62. metadata +44 -31
  63. data/lib/mongo_mapper/associations/base.rb +0 -119
  64. data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +0 -26
  65. data/lib/mongo_mapper/associations/belongs_to_proxy.rb +0 -21
  66. data/lib/mongo_mapper/associations/collection.rb +0 -19
  67. data/lib/mongo_mapper/associations/in_array_proxy.rb +0 -137
  68. data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +0 -26
  69. data/lib/mongo_mapper/associations/many_documents_proxy.rb +0 -115
  70. data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +0 -31
  71. data/lib/mongo_mapper/associations/many_embedded_proxy.rb +0 -54
  72. data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +0 -11
  73. data/lib/mongo_mapper/associations/one_proxy.rb +0 -64
  74. data/lib/mongo_mapper/associations/proxy.rb +0 -116
  75. data/lib/mongo_mapper/associations.rb +0 -78
  76. data/lib/mongo_mapper/callbacks.rb +0 -61
  77. data/lib/mongo_mapper/dirty.rb +0 -117
  78. data/lib/mongo_mapper/key.rb +0 -36
  79. data/lib/mongo_mapper/mongo_mapper.rb +0 -125
  80. data/lib/mongo_mapper/pagination.rb +0 -66
  81. data/lib/mongo_mapper/rails_compatibility/document.rb +0 -15
  82. data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +0 -28
  83. data/lib/mongo_mapper/serialization.rb +0 -54
  84. data/lib/mongo_mapper/serializers/json_serializer.rb +0 -48
  85. data/lib/mongo_mapper/validations.rb +0 -39
  86. data/test/functional/test_rails_compatibility.rb +0 -25
@@ -1,117 +0,0 @@
1
- module MongoMapper
2
- module Dirty
3
- DIRTY_SUFFIXES = ['_changed?', '_change', '_will_change!', '_was']
4
-
5
- def method_missing(method, *args, &block)
6
- if method.to_s =~ /(_changed\?|_change|_will_change!|_was)$/
7
- method_suffix = $1
8
- key = method.to_s.gsub(method_suffix, '')
9
-
10
- if key_names.include?(key)
11
- case method_suffix
12
- when '_changed?'
13
- key_changed?(key)
14
- when '_change'
15
- key_change(key)
16
- when '_will_change!'
17
- key_will_change!(key)
18
- when '_was'
19
- key_was(key)
20
- end
21
- else
22
- super
23
- end
24
- else
25
- super
26
- end
27
- end
28
-
29
- def changed?
30
- !changed_keys.empty?
31
- end
32
-
33
- def changed
34
- changed_keys.keys
35
- end
36
-
37
- def changes
38
- changed.inject({}) { |h, attribute| h[attribute] = key_change(attribute); h }
39
- end
40
-
41
- def initialize(attrs={})
42
- super(attrs)
43
- changed_keys.clear unless new?
44
- end
45
-
46
- def save(*args)
47
- if status = super
48
- changed_keys.clear
49
- end
50
- status
51
- end
52
-
53
- def save!(*args)
54
- status = super
55
- changed_keys.clear
56
- status
57
- end
58
-
59
- def reload(*args)
60
- record = super
61
- changed_keys.clear
62
- record
63
- end
64
-
65
- private
66
- def clone_key_value(attribute_name)
67
- value = send(:read_attribute, attribute_name)
68
- value.duplicable? ? value.clone : value
69
- rescue TypeError, NoMethodError
70
- value
71
- end
72
-
73
- def changed_keys
74
- @changed_keys ||= {}
75
- end
76
-
77
- def key_changed?(attribute)
78
- changed_keys.include?(attribute)
79
- end
80
-
81
- def key_change(attribute)
82
- [changed_keys[attribute], __send__(attribute)] if key_changed?(attribute)
83
- end
84
-
85
- def key_was(attribute)
86
- key_changed?(attribute) ? changed_keys[attribute] : __send__(attribute)
87
- end
88
-
89
- def key_will_change!(attribute)
90
- changed_keys[attribute] = clone_key_value(attribute)
91
- end
92
-
93
- def write_attribute(attribute, value)
94
- attribute = attribute.to_s
95
-
96
- if changed_keys.include?(attribute)
97
- old = changed_keys[attribute]
98
- changed_keys.delete(attribute) unless value_changed?(attribute, old, value)
99
- else
100
- old = clone_key_value(attribute)
101
- changed_keys[attribute] = old if value_changed?(attribute, old, value)
102
- end
103
-
104
- super(attribute, value)
105
- end
106
-
107
- def value_changed?(key_name, old, value)
108
- key = _keys[key_name]
109
-
110
- if key.number? && value.blank?
111
- value = nil
112
- end
113
-
114
- old != value
115
- end
116
- end
117
- end
@@ -1,36 +0,0 @@
1
- module MongoMapper
2
- class Key
3
- attr_accessor :name, :type, :options, :default_value
4
-
5
- def initialize(*args)
6
- options = args.extract_options!
7
- @name, @type = args.shift.to_s, args.shift
8
- self.options = (options || {}).symbolize_keys
9
- self.default_value = self.options.delete(:default)
10
- end
11
-
12
- def ==(other)
13
- @name == other.name && @type == other.type
14
- end
15
-
16
- def set(value)
17
- type.to_mongo(value)
18
- end
19
-
20
- def embeddable?
21
- type.respond_to?(:embeddable?) && type.embeddable? ? true : false
22
- end
23
-
24
- def number?
25
- [Integer, Float].include?(type)
26
- end
27
-
28
- def get(value)
29
- if value.nil? && !default_value.nil?
30
- return default_value
31
- end
32
-
33
- type.from_mongo(value)
34
- end
35
- end
36
- end
@@ -1,125 +0,0 @@
1
- # if Gem is defined i'll assume you are using rubygems and lock specific versions
2
- # call me crazy but a plain old require will just get the latest version you have installed
3
- # so i want to make sure that if you are using gems you do in fact have the correct versions
4
- # if there is a better way to do this, please enlighten me!
5
- if self.class.const_defined?(:Gem)
6
- gem 'activesupport', '>= 2.3'
7
- gem 'mongo', '0.18.2'
8
- gem 'jnunemaker-validatable', '1.8.1'
9
- end
10
-
11
- require 'active_support'
12
- require 'mongo'
13
- require 'validatable'
14
-
15
- module MongoMapper
16
- # generic MM error
17
- class MongoMapperError < StandardError; end
18
-
19
- # raised when key expected to exist but not found
20
- class KeyNotFound < MongoMapperError; end
21
-
22
- # raised when document expected but not found
23
- class DocumentNotFound < MongoMapperError; end
24
-
25
- # raised when document not valid and using !
26
- class DocumentNotValid < MongoMapperError
27
- def initialize(document)
28
- super("Validation failed: #{document.errors.full_messages.join(", ")}")
29
- end
30
- end
31
-
32
- # @api public
33
- def self.connection
34
- @@connection ||= Mongo::Connection.new
35
- end
36
-
37
- # @api public
38
- def self.connection=(new_connection)
39
- @@connection = new_connection
40
- end
41
-
42
- # @api public
43
- def self.logger
44
- connection.logger
45
- end
46
-
47
- # @api public
48
- def self.database=(name)
49
- @@database = nil
50
- @@database_name = name
51
- end
52
-
53
- # @api public
54
- def self.database
55
- if @@database_name.blank?
56
- raise 'You forgot to set the default database name: MongoMapper.database = "foobar"'
57
- end
58
-
59
- @@database ||= MongoMapper.connection.db(@@database_name)
60
- end
61
-
62
- # @api private
63
- def self.ensured_indexes
64
- @@ensured_indexes ||= []
65
- end
66
-
67
- # @api private
68
- def self.ensured_indexes=(value)
69
- @@ensured_indexes = value
70
- end
71
-
72
- # @api private
73
- def self.ensure_index(klass, keys, options={})
74
- ensured_indexes << {:klass => klass, :keys => keys, :options => options}
75
- end
76
-
77
- # @api public
78
- def self.ensure_indexes!
79
- ensured_indexes.each do |index|
80
- unique = index[:options].delete(:unique)
81
- index[:klass].collection.create_index(index[:keys], unique)
82
- end
83
- end
84
-
85
- # @api private
86
- def self.use_time_zone?
87
- Time.respond_to?(:zone) && Time.zone ? true : false
88
- end
89
-
90
- # @api private
91
- def self.time_class
92
- use_time_zone? ? Time.zone : Time
93
- end
94
-
95
- # @api private
96
- def self.normalize_object_id(value)
97
- value.is_a?(String) ? Mongo::ObjectID.from_string(value) : value
98
- end
99
- end
100
-
101
- require 'mongo_mapper/support'
102
- require 'mongo_mapper/callbacks'
103
- require 'mongo_mapper/finder_options'
104
- require 'mongo_mapper/dirty'
105
- require 'mongo_mapper/dynamic_finder'
106
- require 'mongo_mapper/key'
107
- require 'mongo_mapper/pagination'
108
- require 'mongo_mapper/serialization'
109
- require 'mongo_mapper/validations'
110
- require 'mongo_mapper/rails_compatibility/document'
111
- require 'mongo_mapper/rails_compatibility/embedded_document'
112
- require 'mongo_mapper/embedded_document'
113
- require 'mongo_mapper/document'
114
- require 'mongo_mapper/associations'
115
- require 'mongo_mapper/associations/base'
116
- require 'mongo_mapper/associations/proxy'
117
- require 'mongo_mapper/associations/collection'
118
- require 'mongo_mapper/associations/many_documents_proxy'
119
- require 'mongo_mapper/associations/belongs_to_proxy'
120
- require 'mongo_mapper/associations/belongs_to_polymorphic_proxy'
121
- require 'mongo_mapper/associations/many_polymorphic_proxy'
122
- require 'mongo_mapper/associations/many_embedded_proxy'
123
- require 'mongo_mapper/associations/many_embedded_polymorphic_proxy'
124
- require 'mongo_mapper/associations/many_documents_as_proxy'
125
- require 'mongo_mapper/associations/one_proxy'
@@ -1,66 +0,0 @@
1
- module MongoMapper
2
- module Pagination
3
- class PaginationProxy
4
- instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^object_id$)/ }
5
-
6
- attr_accessor :subject
7
- attr_reader :total_entries, :per_page, :current_page
8
- alias limit per_page
9
-
10
- def initialize(total_entries, current_page, per_page=nil)
11
- @total_entries = total_entries.to_i
12
- self.per_page = per_page
13
- self.current_page = current_page
14
- end
15
-
16
- def total_pages
17
- (total_entries / per_page.to_f).ceil
18
- end
19
-
20
- def out_of_bounds?
21
- current_page > total_pages
22
- end
23
-
24
- def previous_page
25
- current_page > 1 ? (current_page - 1) : nil
26
- end
27
-
28
- def next_page
29
- current_page < total_pages ? (current_page + 1) : nil
30
- end
31
-
32
- def skip
33
- (current_page - 1) * per_page
34
- end
35
- alias offset skip # for will paginate support
36
-
37
- def send(method, *args, &block)
38
- if respond_to?(method)
39
- super
40
- else
41
- subject.send(method, *args, &block)
42
- end
43
- end
44
-
45
- def ===(other)
46
- other === subject
47
- end
48
-
49
- def method_missing(name, *args, &block)
50
- @subject.send(name, *args, &block)
51
- end
52
-
53
- private
54
- def per_page=(value)
55
- value = 25 if value.blank?
56
- @per_page = value.to_i
57
- end
58
-
59
- def current_page=(value)
60
- value = value.to_i
61
- value = 1 if value < 1
62
- @current_page = value
63
- end
64
- end
65
- end
66
- end
@@ -1,15 +0,0 @@
1
- module MongoMapper
2
- module RailsCompatibility
3
- module Document
4
- def self.included(model)
5
- model.class_eval do
6
- alias_method :new_record?, :new?
7
-
8
- def human_name
9
- self.name.demodulize.titleize
10
- end
11
- end
12
- end
13
- end
14
- end
15
- end
@@ -1,28 +0,0 @@
1
- module MongoMapper
2
- module RailsCompatibility
3
- module EmbeddedDocument
4
- def self.included(model)
5
- model.class_eval do
6
- extend ClassMethods
7
-
8
- alias_method :new_record?, :new?
9
- end
10
-
11
- class << model
12
- alias has_many many
13
- alias has_one one
14
- end
15
- end
16
-
17
- module ClassMethods
18
- def column_names
19
- keys.keys
20
- end
21
-
22
- def human_name
23
- self.name.demodulize.titleize
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,54 +0,0 @@
1
- require 'active_support/json'
2
-
3
- module MongoMapper
4
- module Serialization
5
- class Serializer
6
- attr_reader :options
7
-
8
- def initialize(record, options={})
9
- @record, @options = record, options.dup
10
- end
11
-
12
- def serializable_key_names
13
- key_names = @record.attributes.keys
14
-
15
- if options[:only]
16
- options.delete(:except)
17
- key_names = key_names & Array(options[:only]).collect { |n| n.to_s }
18
- else
19
- options[:except] = Array(options[:except])
20
- key_names = key_names - options[:except].collect { |n| n.to_s }
21
- end
22
-
23
- key_names
24
- end
25
-
26
- def serializable_method_names
27
- Array(options[:methods]).inject([]) do |method_attributes, name|
28
- method_attributes << name if @record.respond_to?(name.to_s)
29
- method_attributes
30
- end
31
- end
32
-
33
- def serializable_names
34
- serializable_key_names + serializable_method_names
35
- end
36
-
37
- def serializable_record
38
- returning(serializable_record = {}) do
39
- serializable_names.each { |name| serializable_record[name] = @record.send(name) }
40
- end
41
- end
42
-
43
- def serialize
44
- # overwrite to implement
45
- end
46
-
47
- def to_s(&block)
48
- serialize(&block)
49
- end
50
- end
51
- end
52
- end
53
-
54
- require 'mongo_mapper/serializers/json_serializer'
@@ -1,48 +0,0 @@
1
- module MongoMapper
2
- module Serialization
3
- def self.included(base)
4
- base.cattr_accessor :include_root_in_json, :instance_writer => false
5
- base.extend ClassMethods
6
- end
7
-
8
- def to_json(options={})
9
- apply_to_json_defaults(options)
10
-
11
- if include_root_in_json
12
- "{#{self.class.json_class_name}: #{JsonSerializer.new(self, options).to_s}}"
13
- else
14
- JsonSerializer.new(self, options).to_s
15
- end
16
- end
17
-
18
- def from_json(json)
19
- self.attributes = ActiveSupport::JSON.decode(json)
20
- self
21
- end
22
-
23
- class JsonSerializer < MongoMapper::Serialization::Serializer
24
- def serialize
25
- serializable_record.to_json
26
- end
27
- end
28
-
29
- module ClassMethods
30
- def json_class_name
31
- @json_class_name ||= name.demodulize.underscore.inspect
32
- end
33
- end
34
-
35
- private
36
- def apply_to_json_defaults(options)
37
- unless options[:only]
38
- methods = [options.delete(:methods)].flatten.compact
39
- methods << :id
40
- options[:methods] = methods.uniq
41
- end
42
-
43
- except = [options.delete(:except)].flatten.compact
44
- except << :_id
45
- options[:except] = except
46
- end
47
- end
48
- end
@@ -1,39 +0,0 @@
1
- module MongoMapper
2
- module Validations
3
- module Macros
4
- def validates_uniqueness_of(*args)
5
- add_validations(args, MongoMapper::Validations::ValidatesUniquenessOf)
6
- end
7
- end
8
-
9
- class ValidatesUniquenessOf < Validatable::ValidationBase
10
- option :scope, :case_sensitive
11
- default :case_sensitive => true
12
-
13
- def valid?(instance)
14
- value = instance[attribute]
15
- return true if allow_blank && value.blank?
16
- base_conditions = case_sensitive ? {self.attribute => value} : {}
17
- doc = instance.class.first(base_conditions.merge(scope_conditions(instance)).merge(where_conditions(instance)))
18
- doc.nil? || instance._id == doc._id
19
- end
20
-
21
- def message(instance)
22
- super || "has already been taken"
23
- end
24
-
25
- def scope_conditions(instance)
26
- return {} unless scope
27
- Array(scope).inject({}) do |conditions, key|
28
- conditions.merge(key => instance[key])
29
- end
30
- end
31
-
32
- def where_conditions(instance)
33
- conditions = {}
34
- conditions[attribute] = /#{instance[attribute].to_s}/i unless case_sensitive
35
- conditions
36
- end
37
- end
38
- end
39
- end
@@ -1,25 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestRailsCompatibility < Test::Unit::TestCase
4
- class Item
5
- include MongoMapper::EmbeddedDocument
6
- key :for_all, String
7
- end
8
-
9
- class Order
10
- include MongoMapper::Document
11
- many :items, :class_name => 'TestRailsCompatibility::Item'
12
- key :order_only, String
13
- end
14
-
15
- context "Document" do
16
- setup do
17
- Order.collection.remove
18
- end
19
-
20
- should "alias new to new_record?" do
21
- instance = Order.new
22
- instance.new_record?.should == instance.new?
23
- end
24
- end
25
- end