djsun-mongo_mapper 0.5.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/.gitignore +8 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +39 -0
  4. data/Rakefile +87 -0
  5. data/VERSION +1 -0
  6. data/bin/mmconsole +55 -0
  7. data/lib/mongo_mapper/associations/base.rb +83 -0
  8. data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +34 -0
  9. data/lib/mongo_mapper/associations/belongs_to_proxy.rb +22 -0
  10. data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +27 -0
  11. data/lib/mongo_mapper/associations/many_documents_proxy.rb +116 -0
  12. data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +33 -0
  13. data/lib/mongo_mapper/associations/many_embedded_proxy.rb +67 -0
  14. data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +11 -0
  15. data/lib/mongo_mapper/associations/many_proxy.rb +6 -0
  16. data/lib/mongo_mapper/associations/proxy.rb +74 -0
  17. data/lib/mongo_mapper/associations.rb +86 -0
  18. data/lib/mongo_mapper/callbacks.rb +106 -0
  19. data/lib/mongo_mapper/document.rb +308 -0
  20. data/lib/mongo_mapper/dynamic_finder.rb +35 -0
  21. data/lib/mongo_mapper/embedded_document.rb +354 -0
  22. data/lib/mongo_mapper/finder_options.rb +94 -0
  23. data/lib/mongo_mapper/key.rb +32 -0
  24. data/lib/mongo_mapper/observing.rb +50 -0
  25. data/lib/mongo_mapper/pagination.rb +51 -0
  26. data/lib/mongo_mapper/rails_compatibility/document.rb +15 -0
  27. data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +27 -0
  28. data/lib/mongo_mapper/save_with_validation.rb +19 -0
  29. data/lib/mongo_mapper/serialization.rb +55 -0
  30. data/lib/mongo_mapper/serializers/json_serializer.rb +92 -0
  31. data/lib/mongo_mapper/support.rb +171 -0
  32. data/lib/mongo_mapper/validations.rb +69 -0
  33. data/lib/mongo_mapper.rb +95 -0
  34. data/mongo_mapper.gemspec +156 -0
  35. data/specs.watchr +32 -0
  36. data/test/NOTE_ON_TESTING +1 -0
  37. data/test/custom_matchers.rb +48 -0
  38. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +55 -0
  39. data/test/functional/associations/test_belongs_to_proxy.rb +49 -0
  40. data/test/functional/associations/test_many_documents_as_proxy.rb +244 -0
  41. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +132 -0
  42. data/test/functional/associations/test_many_embedded_proxy.rb +174 -0
  43. data/test/functional/associations/test_many_polymorphic_proxy.rb +297 -0
  44. data/test/functional/associations/test_many_proxy.rb +331 -0
  45. data/test/functional/test_associations.rb +44 -0
  46. data/test/functional/test_binary.rb +18 -0
  47. data/test/functional/test_callbacks.rb +85 -0
  48. data/test/functional/test_document.rb +964 -0
  49. data/test/functional/test_embedded_document.rb +97 -0
  50. data/test/functional/test_logger.rb +20 -0
  51. data/test/functional/test_pagination.rb +87 -0
  52. data/test/functional/test_rails_compatibility.rb +30 -0
  53. data/test/functional/test_validations.rb +279 -0
  54. data/test/models.rb +169 -0
  55. data/test/test_helper.rb +30 -0
  56. data/test/unit/serializers/test_json_serializer.rb +193 -0
  57. data/test/unit/test_association_base.rb +144 -0
  58. data/test/unit/test_document.rb +165 -0
  59. data/test/unit/test_dynamic_finder.rb +125 -0
  60. data/test/unit/test_embedded_document.rb +643 -0
  61. data/test/unit/test_finder_options.rb +193 -0
  62. data/test/unit/test_key.rb +175 -0
  63. data/test/unit/test_mongomapper.rb +28 -0
  64. data/test/unit/test_observing.rb +101 -0
  65. data/test/unit/test_pagination.rb +109 -0
  66. data/test/unit/test_rails_compatibility.rb +39 -0
  67. data/test/unit/test_serializations.rb +52 -0
  68. data/test/unit/test_support.rb +272 -0
  69. data/test/unit/test_time_zones.rb +40 -0
  70. data/test/unit/test_validations.rb +503 -0
  71. metadata +207 -0
@@ -0,0 +1,92 @@
1
+ module MongoMapper #:nodoc:
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
+ # Returns a JSON string representing the model. Some configuration is
9
+ # available through +options+.
10
+ #
11
+ # The option <tt>include_root_in_json</tt> controls the top-level behavior of
12
+ # to_json. When it is <tt>true</tt>, to_json will emit a single root node named
13
+ # after the object's type. For example:
14
+ #
15
+ # konata = User.find(1)
16
+ # User.include_root_in_json = true
17
+ # konata.to_json
18
+ # # => { "user": {"id": 1, "name": "Konata Izumi", "age": 16,
19
+ # "created_at": "2006/08/01", "awesome": true} }
20
+ #
21
+ # User.include_root_in_json = false
22
+ # konata.to_json
23
+ # # => {"id": 1, "name": "Konata Izumi", "age": 16,
24
+ # "created_at": "2006/08/01", "awesome": true}
25
+ #
26
+ # The remainder of the examples in this section assume include_root_in_json is set to
27
+ # <tt>false</tt>.
28
+ #
29
+ # Without any +options+, the returned JSON string will include all
30
+ # the model's attributes. For example:
31
+ #
32
+ # konata = User.find(1)
33
+ # konata.to_json
34
+ # # => {"id": 1, "name": "Konata Izumi", "age": 16,
35
+ # "created_at": "2006/08/01", "awesome": true}
36
+ #
37
+ # The <tt>:only</tt> and <tt>:except</tt> options can be used to limit the attributes
38
+ # included, and work similar to the +attributes+ method. For example:
39
+ #
40
+ # konata.to_json(:only => [ :id, :name ])
41
+ # # => {"id": 1, "name": "Konata Izumi"}
42
+ #
43
+ # konata.to_json(:except => [ :id, :created_at, :age ])
44
+ # # => {"name": "Konata Izumi", "awesome": true}
45
+ #
46
+ # To include any methods on the model, use <tt>:methods</tt>.
47
+ #
48
+ # konata.to_json(:methods => :permalink)
49
+ # # => {"id": 1, "name": "Konata Izumi", "age": 16,
50
+ # "created_at": "2006/08/01", "awesome": true,
51
+ # "permalink": "1-konata-izumi"}
52
+ def to_json(options = {})
53
+ apply_to_json_defaults(options)
54
+
55
+ if include_root_in_json
56
+ "{#{self.class.json_class_name}: #{JsonSerializer.new(self, options).to_s}}"
57
+ else
58
+ JsonSerializer.new(self, options).to_s
59
+ end
60
+ end
61
+
62
+ def from_json(json)
63
+ self.attributes = ActiveSupport::JSON.decode(json)
64
+ self
65
+ end
66
+
67
+ class JsonSerializer < MongoMapper::Serialization::Serializer #:nodoc:
68
+ def serialize
69
+ serializable_record.to_json
70
+ end
71
+ end
72
+
73
+ module ClassMethods
74
+ def json_class_name
75
+ @json_class_name ||= name.demodulize.underscore.inspect
76
+ end
77
+ end
78
+
79
+ private
80
+ def apply_to_json_defaults(options)
81
+ unless options[:only]
82
+ methods = [options.delete(:methods)].flatten.compact
83
+ methods << :id
84
+ options[:methods] = methods.uniq
85
+ end
86
+
87
+ except = [options.delete(:except)].flatten.compact
88
+ except << :_id
89
+ options[:except] = except
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,171 @@
1
+ class BasicObject #:nodoc:
2
+ instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|^methods$|instance_eval|proxy_|^object_id$)/ }
3
+ end unless defined?(BasicObject)
4
+
5
+ class Array
6
+ def self.to_mongo(value)
7
+ value.to_a
8
+ end
9
+
10
+ def self.from_mongo(value)
11
+ value || []
12
+ end
13
+ end
14
+
15
+ class Binary
16
+ def self.to_mongo(value)
17
+ if value.is_a?(ByteBuffer)
18
+ value
19
+ else
20
+ value.nil? ? nil : ByteBuffer.new(value)
21
+ end
22
+ end
23
+
24
+ def self.from_mongo(value)
25
+ value
26
+ end
27
+ end
28
+
29
+ class Boolean
30
+ def self.to_mongo(value)
31
+ if value.is_a?(Boolean)
32
+ value
33
+ else
34
+ ['true', 't', '1'].include?(value.to_s.downcase)
35
+ end
36
+ end
37
+
38
+ def self.from_mongo(value)
39
+ !!value
40
+ end
41
+ end
42
+
43
+ class Date
44
+ def self.to_mongo(value)
45
+ date = Date.parse(value.to_s)
46
+ Time.utc(date.year, date.month, date.day)
47
+ rescue
48
+ nil
49
+ end
50
+
51
+ def self.from_mongo(value)
52
+ value.to_date if value.present?
53
+ end
54
+ end
55
+
56
+ class Float
57
+ def self.to_mongo(value)
58
+ value.to_f
59
+ end
60
+ end
61
+
62
+ class Hash
63
+ def self.from_mongo(value)
64
+ HashWithIndifferentAccess.new(value || {})
65
+ end
66
+
67
+ def to_mongo
68
+ self
69
+ end
70
+ end
71
+
72
+ class Integer
73
+ def self.to_mongo(value)
74
+ value_to_i = value.to_i
75
+ if value_to_i == 0
76
+ value.to_s =~ /^(0x|0b)?0+/ ? 0 : nil
77
+ else
78
+ value_to_i
79
+ end
80
+ end
81
+ end
82
+
83
+ class NilClass
84
+ def to_mongo(value)
85
+ value
86
+ end
87
+
88
+ def from_mongo(value)
89
+ value
90
+ end
91
+ end
92
+
93
+ class Object
94
+ # The hidden singleton lurks behind everyone
95
+ def metaclass
96
+ class << self; self end
97
+ end
98
+
99
+ def meta_eval(&blk)
100
+ metaclass.instance_eval(&blk)
101
+ end
102
+
103
+ # Adds methods to a metaclass
104
+ def meta_def(name, &blk)
105
+ meta_eval { define_method(name, &blk) }
106
+ end
107
+
108
+ # Defines an instance method within a class
109
+ def class_def(name, &blk)
110
+ class_eval { define_method(name, &blk) }
111
+ end
112
+
113
+ def self.to_mongo(value)
114
+ value
115
+ end
116
+
117
+ def self.from_mongo(value)
118
+ value
119
+ end
120
+ end
121
+
122
+ class String
123
+ def self.to_mongo(value)
124
+ value.nil? ? nil : value.to_s
125
+ end
126
+
127
+ def self.from_mongo(value)
128
+ value.nil? ? nil : value.to_s
129
+ end
130
+ end
131
+
132
+ class Time
133
+ def self.to_mongo(value)
134
+ to_utc_time(value)
135
+ end
136
+
137
+ def self.from_mongo(value)
138
+ if Time.respond_to?(:zone) && Time.zone && value.present?
139
+ value.in_time_zone(Time.zone)
140
+ else
141
+ value
142
+ end
143
+ end
144
+
145
+ def self.to_utc_time(value)
146
+ to_local_time(value).try(:utc)
147
+ end
148
+
149
+ # make sure we have a time and that it is local
150
+ def self.to_local_time(value)
151
+ if Time.respond_to?(:zone) && Time.zone
152
+ Time.zone.parse(value.to_s)
153
+ else
154
+ Time.parse(value.to_s)
155
+ end
156
+ end
157
+ end
158
+
159
+ # duck punch to get access to internal mongo
160
+ # logger instance until my patch goes thorugh
161
+ module Mongo
162
+ class Connection
163
+ def logger
164
+ @options[:logger]
165
+ end
166
+ end
167
+
168
+ class DB
169
+ attr_reader :logger
170
+ end
171
+ end
@@ -0,0 +1,69 @@
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
+
8
+ def validates_exclusion_of(*args)
9
+ add_validations(args, MongoMapper::Validations::ValidatesExclusionOf)
10
+ end
11
+
12
+ def validates_inclusion_of(*args)
13
+ add_validations(args, MongoMapper::Validations::ValidatesInclusionOf)
14
+ end
15
+ end
16
+
17
+ class ValidatesUniquenessOf < Validatable::ValidationBase
18
+ option :scope
19
+
20
+ def valid?(instance)
21
+ doc = instance.class.find(:first, :conditions => {self.attribute => instance[attribute]}.merge(scope_conditions(instance)), :limit => 1)
22
+ doc.nil? || instance.id == doc.id
23
+ end
24
+
25
+ def message(instance)
26
+ super || "has already been taken"
27
+ end
28
+
29
+ def scope_conditions(instance)
30
+ return {} unless scope
31
+ Array(scope).inject({}) do |conditions, key|
32
+ conditions.merge(key => instance[key])
33
+ end
34
+ end
35
+ end
36
+
37
+ class ValidatesExclusionOf < Validatable::ValidationBase
38
+ required_option :within
39
+
40
+ def valid?(instance)
41
+ value = instance[attribute]
42
+ return true if allow_nil && value.nil?
43
+ return true if allow_blank && value.blank?
44
+
45
+ !within.include?(instance[attribute])
46
+ end
47
+
48
+ def message(instance)
49
+ super || "is reserved"
50
+ end
51
+ end
52
+
53
+ class ValidatesInclusionOf < Validatable::ValidationBase
54
+ required_option :within
55
+
56
+ def valid?(instance)
57
+ value = instance[attribute]
58
+ return true if allow_nil && value.nil?
59
+ return true if allow_blank && value.blank?
60
+
61
+ within.include?(value)
62
+ end
63
+
64
+ def message(instance)
65
+ super || "is not in the list"
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,95 @@
1
+ require 'rubygems'
2
+
3
+ gem 'activesupport'
4
+ gem 'mongo', '0.15'
5
+ gem 'jnunemaker-validatable', '1.7.3'
6
+
7
+ require 'activesupport'
8
+ require 'mongo'
9
+ require 'validatable'
10
+
11
+ module MongoMapper
12
+ DocumentNotFound = Class.new(StandardError)
13
+ DocumentNotValid = Class.new(StandardError) do
14
+ def initialize(document)
15
+ @document = document
16
+ super("Validation failed: #{@document.errors.full_messages.join(", ")}")
17
+ end
18
+ end
19
+
20
+ def self.connection
21
+ @@connection ||= Mongo::Connection.new
22
+ end
23
+
24
+ def self.connection=(new_connection)
25
+ @@connection = new_connection
26
+ end
27
+
28
+ def self.logger
29
+ connection.logger
30
+ end
31
+
32
+ def self.database=(name)
33
+ @@database = nil
34
+ @@database_name = name
35
+ end
36
+
37
+ def self.database
38
+ if @@database_name.blank?
39
+ raise 'You forgot to set the default database name: MongoMapper.database = "foobar"'
40
+ end
41
+
42
+ @@database ||= MongoMapper.connection.db(@@database_name)
43
+ end
44
+
45
+ module Finders
46
+ def dynamic_find(finder, args)
47
+ attributes = {}
48
+ find_options = args.extract_options!.deep_merge(:conditions => attributes)
49
+
50
+ finder.attributes.each_with_index do |attr, index|
51
+ attributes[attr] = args[index]
52
+ end
53
+
54
+ result = find(finder.finder, find_options)
55
+
56
+ if result.nil?
57
+ if finder.bang
58
+ raise DocumentNotFound, "Couldn't find Document with #{attributes.inspect} in collection named #{collection.name}"
59
+ end
60
+
61
+ if finder.instantiator
62
+ self.send(finder.instantiator, attributes)
63
+ end
64
+ else
65
+ result
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ require 'mongo_mapper/support'
72
+ require 'mongo_mapper/associations'
73
+ require 'mongo_mapper/associations/base'
74
+ require 'mongo_mapper/associations/proxy'
75
+ require 'mongo_mapper/associations/many_documents_proxy'
76
+ require 'mongo_mapper/associations/belongs_to_proxy'
77
+ require 'mongo_mapper/associations/belongs_to_polymorphic_proxy'
78
+ require 'mongo_mapper/associations/many_proxy'
79
+ require 'mongo_mapper/associations/many_polymorphic_proxy'
80
+ require 'mongo_mapper/associations/many_embedded_proxy'
81
+ require 'mongo_mapper/associations/many_embedded_polymorphic_proxy'
82
+ require 'mongo_mapper/associations/many_documents_as_proxy'
83
+ require 'mongo_mapper/callbacks'
84
+ require 'mongo_mapper/finder_options'
85
+ require 'mongo_mapper/dynamic_finder'
86
+ require 'mongo_mapper/key'
87
+ require 'mongo_mapper/observing'
88
+ require 'mongo_mapper/pagination'
89
+ require 'mongo_mapper/save_with_validation'
90
+ require 'mongo_mapper/serialization'
91
+ require 'mongo_mapper/validations'
92
+ require 'mongo_mapper/rails_compatibility/document'
93
+ require 'mongo_mapper/rails_compatibility/embedded_document'
94
+ require 'mongo_mapper/embedded_document'
95
+ require 'mongo_mapper/document'
@@ -0,0 +1,156 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{mongo_mapper}
8
+ s.version = "0.5.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["John Nunemaker"]
12
+ s.date = %q{2009-10-07}
13
+ s.default_executable = %q{mmconsole}
14
+ s.email = %q{nunemaker@gmail.com}
15
+ s.executables = ["mmconsole"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "bin/mmconsole",
27
+ "lib/mongo_mapper.rb",
28
+ "lib/mongo_mapper/associations.rb",
29
+ "lib/mongo_mapper/associations/base.rb",
30
+ "lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb",
31
+ "lib/mongo_mapper/associations/belongs_to_proxy.rb",
32
+ "lib/mongo_mapper/associations/many_documents_as_proxy.rb",
33
+ "lib/mongo_mapper/associations/many_documents_proxy.rb",
34
+ "lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb",
35
+ "lib/mongo_mapper/associations/many_embedded_proxy.rb",
36
+ "lib/mongo_mapper/associations/many_polymorphic_proxy.rb",
37
+ "lib/mongo_mapper/associations/many_proxy.rb",
38
+ "lib/mongo_mapper/associations/proxy.rb",
39
+ "lib/mongo_mapper/callbacks.rb",
40
+ "lib/mongo_mapper/document.rb",
41
+ "lib/mongo_mapper/dynamic_finder.rb",
42
+ "lib/mongo_mapper/embedded_document.rb",
43
+ "lib/mongo_mapper/finder_options.rb",
44
+ "lib/mongo_mapper/key.rb",
45
+ "lib/mongo_mapper/observing.rb",
46
+ "lib/mongo_mapper/pagination.rb",
47
+ "lib/mongo_mapper/rails_compatibility/document.rb",
48
+ "lib/mongo_mapper/rails_compatibility/embedded_document.rb",
49
+ "lib/mongo_mapper/save_with_validation.rb",
50
+ "lib/mongo_mapper/serialization.rb",
51
+ "lib/mongo_mapper/serializers/json_serializer.rb",
52
+ "lib/mongo_mapper/support.rb",
53
+ "lib/mongo_mapper/validations.rb",
54
+ "mongo_mapper.gemspec",
55
+ "test/NOTE_ON_TESTING",
56
+ "test/custom_matchers.rb",
57
+ "test/functional/associations/test_belongs_to_polymorphic_proxy.rb",
58
+ "test/functional/associations/test_belongs_to_proxy.rb",
59
+ "test/functional/associations/test_many_documents_as_proxy.rb",
60
+ "test/functional/associations/test_many_embedded_polymorphic_proxy.rb",
61
+ "test/functional/associations/test_many_embedded_proxy.rb",
62
+ "test/functional/associations/test_many_polymorphic_proxy.rb",
63
+ "test/functional/associations/test_many_proxy.rb",
64
+ "test/functional/test_associations.rb",
65
+ "test/functional/test_binary.rb",
66
+ "test/functional/test_callbacks.rb",
67
+ "test/functional/test_document.rb",
68
+ "test/functional/test_embedded_document.rb",
69
+ "test/functional/test_pagination.rb",
70
+ "test/functional/test_rails_compatibility.rb",
71
+ "test/functional/test_validations.rb",
72
+ "test/models.rb",
73
+ "test/test_helper.rb",
74
+ "test/unit/serializers/test_json_serializer.rb",
75
+ "test/unit/test_association_base.rb",
76
+ "test/unit/test_document.rb",
77
+ "test/unit/test_dynamic_finder.rb",
78
+ "test/unit/test_embedded_document.rb",
79
+ "test/unit/test_finder_options.rb",
80
+ "test/unit/test_key.rb",
81
+ "test/unit/test_mongomapper.rb",
82
+ "test/unit/test_observing.rb",
83
+ "test/unit/test_pagination.rb",
84
+ "test/unit/test_rails_compatibility.rb",
85
+ "test/unit/test_serializations.rb",
86
+ "test/unit/test_support.rb",
87
+ "test/unit/test_time_zones.rb",
88
+ "test/unit/test_validations.rb"
89
+ ]
90
+ s.homepage = %q{http://github.com/jnunemaker/mongomapper}
91
+ s.rdoc_options = ["--charset=UTF-8"]
92
+ s.require_paths = ["lib"]
93
+ s.rubyforge_project = %q{mongomapper}
94
+ s.rubygems_version = %q{1.3.5}
95
+ s.summary = %q{Awesome gem for modeling your domain and storing it in mongo}
96
+ s.test_files = [
97
+ "test/custom_matchers.rb",
98
+ "test/functional/associations/test_belongs_to_polymorphic_proxy.rb",
99
+ "test/functional/associations/test_belongs_to_proxy.rb",
100
+ "test/functional/associations/test_many_documents_as_proxy.rb",
101
+ "test/functional/associations/test_many_embedded_polymorphic_proxy.rb",
102
+ "test/functional/associations/test_many_embedded_proxy.rb",
103
+ "test/functional/associations/test_many_polymorphic_proxy.rb",
104
+ "test/functional/associations/test_many_proxy.rb",
105
+ "test/functional/test_associations.rb",
106
+ "test/functional/test_binary.rb",
107
+ "test/functional/test_callbacks.rb",
108
+ "test/functional/test_document.rb",
109
+ "test/functional/test_embedded_document.rb",
110
+ "test/functional/test_pagination.rb",
111
+ "test/functional/test_rails_compatibility.rb",
112
+ "test/functional/test_validations.rb",
113
+ "test/models.rb",
114
+ "test/test_helper.rb",
115
+ "test/unit/serializers/test_json_serializer.rb",
116
+ "test/unit/test_association_base.rb",
117
+ "test/unit/test_document.rb",
118
+ "test/unit/test_dynamic_finder.rb",
119
+ "test/unit/test_embedded_document.rb",
120
+ "test/unit/test_finder_options.rb",
121
+ "test/unit/test_key.rb",
122
+ "test/unit/test_mongomapper.rb",
123
+ "test/unit/test_observing.rb",
124
+ "test/unit/test_pagination.rb",
125
+ "test/unit/test_rails_compatibility.rb",
126
+ "test/unit/test_serializations.rb",
127
+ "test/unit/test_support.rb",
128
+ "test/unit/test_time_zones.rb",
129
+ "test/unit/test_validations.rb"
130
+ ]
131
+
132
+ if s.respond_to? :specification_version then
133
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
134
+ s.specification_version = 3
135
+
136
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
137
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
138
+ s.add_runtime_dependency(%q<mongo>, ["= 0.15"])
139
+ s.add_runtime_dependency(%q<jnunemaker-validatable>, ["= 1.7.3"])
140
+ s.add_development_dependency(%q<mocha>, ["= 0.9.4"])
141
+ s.add_development_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
142
+ else
143
+ s.add_dependency(%q<activesupport>, [">= 0"])
144
+ s.add_dependency(%q<mongo>, ["= 0.15"])
145
+ s.add_dependency(%q<jnunemaker-validatable>, ["= 1.7.3"])
146
+ s.add_dependency(%q<mocha>, ["= 0.9.4"])
147
+ s.add_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
148
+ end
149
+ else
150
+ s.add_dependency(%q<activesupport>, [">= 0"])
151
+ s.add_dependency(%q<mongo>, ["= 0.15"])
152
+ s.add_dependency(%q<jnunemaker-validatable>, ["= 1.7.3"])
153
+ s.add_dependency(%q<mocha>, ["= 0.9.4"])
154
+ s.add_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
155
+ end
156
+ end
data/specs.watchr ADDED
@@ -0,0 +1,32 @@
1
+ def run(cmd)
2
+ puts(cmd)
3
+ system(cmd)
4
+ end
5
+
6
+ def run_test_file(file)
7
+ run "ruby -Itest #{file}"
8
+ end
9
+
10
+ def run_all_tests
11
+ run "rake test"
12
+ end
13
+
14
+ def related_test_files(path)
15
+ Dir['test/**/*.rb'].select { |file| file =~ /#{File.basename(path)}/ }
16
+ end
17
+
18
+ watch('test/test_helper\.rb') { run_all_tests }
19
+ watch('test/.*/test_.*\.rb') { |m| run_test_file(m[0]) }
20
+ watch('lib/.*') do |m|
21
+ related_test_files(m[0]).each { |file| run_test_file(file) }
22
+ end
23
+
24
+ # Ctrl-\
25
+ Signal.trap('QUIT') do
26
+ puts " --- Running all tests ---\n\n"
27
+ run_all_tests
28
+ end
29
+
30
+ # Ctrl-C
31
+ Signal.trap('INT') { abort("\n") }
32
+
@@ -0,0 +1 @@
1
+ I am doing my best to keep unit and functional tests separate. As I see them, functional tests hit the database and should never care about internals. Unit tests do not hit the database.
@@ -0,0 +1,48 @@
1
+ module CustomMatchers
2
+ custom_matcher :be_nil do |receiver, matcher, args|
3
+ matcher.positive_failure_message = "Expected #{receiver} to be nil but it wasn't"
4
+ matcher.negative_failure_message = "Expected #{receiver} not to be nil but it was"
5
+ receiver.nil?
6
+ end
7
+
8
+ custom_matcher :be_blank do |receiver, matcher, args|
9
+ matcher.positive_failure_message = "Expected #{receiver} to be blank but it wasn't"
10
+ matcher.negative_failure_message = "Expected #{receiver} not to be blank but it was"
11
+ receiver.blank?
12
+ end
13
+
14
+ custom_matcher :be_true do |receiver, matcher, args|
15
+ matcher.positive_failure_message = "Expected #{receiver} to be true but it wasn't"
16
+ matcher.negative_failure_message = "Expected #{receiver} not to be true but it was"
17
+ receiver.eql?(true)
18
+ end
19
+
20
+ custom_matcher :be_false do |receiver, matcher, args|
21
+ matcher.positive_failure_message = "Expected #{receiver} to be false but it wasn't"
22
+ matcher.negative_failure_message = "Expected #{receiver} not to be false but it was"
23
+ receiver.eql?(false)
24
+ end
25
+
26
+ custom_matcher :be_valid do |receiver, matcher, args|
27
+ matcher.positive_failure_message = "Expected to be valid but it was invalid #{receiver.errors.inspect}"
28
+ matcher.negative_failure_message = "Expected to be invalid but it was valid #{receiver.errors.inspect}"
29
+ receiver.valid?
30
+ end
31
+
32
+ custom_matcher :have_error_on do |receiver, matcher, args|
33
+ receiver.valid?
34
+ attribute = args[0]
35
+ expected_message = args[1]
36
+
37
+ if expected_message.nil?
38
+ matcher.positive_failure_message = "#{receiver} had no errors on #{attribute}"
39
+ matcher.negative_failure_message = "#{receiver} had errors on #{attribute} #{receiver.errors.inspect}"
40
+ !receiver.errors.on(attribute).blank?
41
+ else
42
+ actual = receiver.errors.on(attribute)
43
+ matcher.positive_failure_message = %Q(Expected error on #{attribute} to be "#{expected_message}" but was "#{actual}")
44
+ matcher.negative_failure_message = %Q(Expected error on #{attribute} not to be "#{expected_message}" but was "#{actual}")
45
+ actual == expected_message
46
+ end
47
+ end
48
+ end