mongomodel 0.5.5 → 0.5.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.
Files changed (156) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +23 -11
  3. data/gemfiles/rails-3.2.gemfile +2 -2
  4. data/gemfiles/rails-4-observers.gemfile +1 -1
  5. data/gemfiles/rails-4.1.gemfile +2 -2
  6. data/gemfiles/{mongoid.gemfile → rails-4.2.gemfile} +2 -3
  7. data/gemfiles/{mongo_mapper.gemfile → rails-5.0.gemfile} +2 -3
  8. data/gemfiles/rails-5.1.gemfile +10 -0
  9. data/gemfiles/rails-5.2.gemfile +10 -0
  10. data/lib/mongomodel.rb +15 -15
  11. data/lib/mongomodel/attributes/mongo.rb +7 -7
  12. data/lib/mongomodel/attributes/store.rb +4 -4
  13. data/lib/mongomodel/attributes/typecasting.rb +7 -7
  14. data/lib/mongomodel/compatibility/mongo_mapper.rb +3 -3
  15. data/lib/mongomodel/compatibility/mongoid.rb +3 -3
  16. data/lib/mongomodel/concerns/abstract_class.rb +3 -3
  17. data/lib/mongomodel/concerns/activemodel.rb +4 -4
  18. data/lib/mongomodel/concerns/associations.rb +8 -8
  19. data/lib/mongomodel/concerns/associations/base/association.rb +5 -5
  20. data/lib/mongomodel/concerns/associations/base/definition.rb +4 -4
  21. data/lib/mongomodel/concerns/associations/base/proxy.rb +1 -1
  22. data/lib/mongomodel/concerns/associations/belongs_to.rb +19 -19
  23. data/lib/mongomodel/concerns/associations/has_many_by_foreign_key.rb +36 -36
  24. data/lib/mongomodel/concerns/associations/has_many_by_ids.rb +34 -34
  25. data/lib/mongomodel/concerns/attribute_methods.rb +10 -10
  26. data/lib/mongomodel/concerns/attribute_methods/before_type_cast.rb +4 -4
  27. data/lib/mongomodel/concerns/attribute_methods/dirty.rb +95 -13
  28. data/lib/mongomodel/concerns/attribute_methods/forbidden.rb +1 -1
  29. data/lib/mongomodel/concerns/attribute_methods/multi_parameter_assignment.rb +6 -6
  30. data/lib/mongomodel/concerns/attribute_methods/nested.rb +18 -18
  31. data/lib/mongomodel/concerns/attribute_methods/protected.rb +3 -3
  32. data/lib/mongomodel/concerns/attribute_methods/query.rb +3 -3
  33. data/lib/mongomodel/concerns/attribute_methods/read.rb +4 -4
  34. data/lib/mongomodel/concerns/attribute_methods/write.rb +4 -4
  35. data/lib/mongomodel/concerns/attributes.rb +18 -18
  36. data/lib/mongomodel/concerns/callbacks.rb +7 -7
  37. data/lib/mongomodel/concerns/document_parent.rb +2 -2
  38. data/lib/mongomodel/concerns/logging.rb +2 -2
  39. data/lib/mongomodel/concerns/map_reduce.rb +11 -11
  40. data/lib/mongomodel/concerns/pretty_inspect.rb +3 -3
  41. data/lib/mongomodel/concerns/properties.rb +18 -18
  42. data/lib/mongomodel/concerns/record_status.rb +9 -13
  43. data/lib/mongomodel/concerns/serialization.rb +4 -4
  44. data/lib/mongomodel/concerns/timestamps.rb +4 -4
  45. data/lib/mongomodel/concerns/translation.rb +2 -2
  46. data/lib/mongomodel/concerns/validations.rb +5 -5
  47. data/lib/mongomodel/concerns/validations/associated.rb +1 -1
  48. data/lib/mongomodel/document.rb +6 -6
  49. data/lib/mongomodel/document/callbacks.rb +15 -21
  50. data/lib/mongomodel/document/collection_modifiers.rb +5 -5
  51. data/lib/mongomodel/document/dynamic_finders.rb +1 -1
  52. data/lib/mongomodel/document/indexes.rb +19 -19
  53. data/lib/mongomodel/document/optimistic_locking.rb +7 -7
  54. data/lib/mongomodel/document/persistence.rb +23 -23
  55. data/lib/mongomodel/document/scopes.rb +20 -20
  56. data/lib/mongomodel/document/validations.rb +6 -6
  57. data/lib/mongomodel/document/validations/uniqueness.rb +11 -11
  58. data/lib/mongomodel/embedded_document.rb +11 -11
  59. data/lib/mongomodel/locale/en.yml +0 -1
  60. data/lib/mongomodel/log_subscriber.rb +5 -5
  61. data/lib/mongomodel/railtie.rb +13 -13
  62. data/lib/mongomodel/support/collection.rb +31 -31
  63. data/lib/mongomodel/support/configuration.rb +11 -11
  64. data/lib/mongomodel/support/core_extensions.rb +1 -1
  65. data/lib/mongomodel/support/dynamic_finder.rb +12 -12
  66. data/lib/mongomodel/support/exceptions.rb +6 -6
  67. data/lib/mongomodel/support/instrumented_collection.rb +20 -20
  68. data/lib/mongomodel/support/map.rb +33 -33
  69. data/lib/mongomodel/support/mongo_operator.rb +6 -6
  70. data/lib/mongomodel/support/mongo_options.rb +18 -18
  71. data/lib/mongomodel/support/mongo_order.rb +16 -16
  72. data/lib/mongomodel/support/paginator.rb +8 -8
  73. data/lib/mongomodel/support/reference.rb +10 -10
  74. data/lib/mongomodel/support/scope.rb +37 -37
  75. data/lib/mongomodel/support/scope/array_methods.rb +1 -1
  76. data/lib/mongomodel/support/scope/batches.rb +1 -1
  77. data/lib/mongomodel/support/scope/dynamic_finders.rb +1 -1
  78. data/lib/mongomodel/support/scope/finder_methods.rb +7 -7
  79. data/lib/mongomodel/support/scope/load_methods.rb +1 -1
  80. data/lib/mongomodel/support/scope/pagination.rb +1 -1
  81. data/lib/mongomodel/support/scope/query_methods.rb +6 -6
  82. data/lib/mongomodel/support/scope/spawn_methods.rb +8 -8
  83. data/lib/mongomodel/support/types.rb +2 -2
  84. data/lib/mongomodel/support/types/array.rb +1 -1
  85. data/lib/mongomodel/support/types/boolean.rb +3 -3
  86. data/lib/mongomodel/support/types/custom.rb +3 -3
  87. data/lib/mongomodel/support/types/date.rb +2 -2
  88. data/lib/mongomodel/support/types/date_time.rb +6 -16
  89. data/lib/mongomodel/support/types/float.rb +1 -1
  90. data/lib/mongomodel/support/types/hash.rb +1 -1
  91. data/lib/mongomodel/support/types/integer.rb +13 -10
  92. data/lib/mongomodel/support/types/object.rb +5 -5
  93. data/lib/mongomodel/support/types/rational.rb +3 -3
  94. data/lib/mongomodel/support/types/time.rb +2 -2
  95. data/lib/mongomodel/version.rb +1 -1
  96. data/lib/rails/generators/mongo_model/config/templates/mongomodel.yml +3 -4
  97. data/lib/rails/generators/mongo_model/model/model_generator.rb +3 -3
  98. data/mongomodel.gemspec +5 -4
  99. data/spec/mongomodel/attributes/store_spec.rb +21 -21
  100. data/spec/mongomodel/concerns/activemodel_spec.rb +4 -4
  101. data/spec/mongomodel/concerns/associations/base/association_spec.rb +12 -12
  102. data/spec/mongomodel/concerns/associations/belongs_to_spec.rb +34 -21
  103. data/spec/mongomodel/concerns/associations/has_many_by_foreign_key_spec.rb +53 -53
  104. data/spec/mongomodel/concerns/associations/has_many_by_ids_spec.rb +30 -30
  105. data/spec/mongomodel/concerns/attribute_methods/before_type_cast_spec.rb +7 -7
  106. data/spec/mongomodel/concerns/attribute_methods/dirty_spec.rb +45 -41
  107. data/spec/mongomodel/concerns/attribute_methods/multi_parameter_assignment_spec.rb +7 -7
  108. data/spec/mongomodel/concerns/attribute_methods/nested_spec.rb +31 -31
  109. data/spec/mongomodel/concerns/attribute_methods/protected_spec.rb +15 -15
  110. data/spec/mongomodel/concerns/attribute_methods/query_spec.rb +19 -19
  111. data/spec/mongomodel/concerns/attribute_methods/read_spec.rb +9 -9
  112. data/spec/mongomodel/concerns/attribute_methods/write_spec.rb +6 -6
  113. data/spec/mongomodel/concerns/attribute_methods_spec.rb +13 -13
  114. data/spec/mongomodel/concerns/attributes_spec.rb +34 -34
  115. data/spec/mongomodel/concerns/callbacks_spec.rb +25 -21
  116. data/spec/mongomodel/concerns/logging_spec.rb +5 -3
  117. data/spec/mongomodel/concerns/map_reduce_spec.rb +19 -19
  118. data/spec/mongomodel/concerns/observing_spec.rb +3 -3
  119. data/spec/mongomodel/concerns/pretty_inspect_spec.rb +10 -10
  120. data/spec/mongomodel/concerns/properties_spec.rb +11 -11
  121. data/spec/mongomodel/concerns/serialization/json_serialization_spec.rb +13 -13
  122. data/spec/mongomodel/concerns/timestamps_spec.rb +39 -39
  123. data/spec/mongomodel/concerns/validations_spec.rb +41 -38
  124. data/spec/mongomodel/document/callbacks_spec.rb +20 -16
  125. data/spec/mongomodel/document/collection_modifiers_spec.rb +16 -16
  126. data/spec/mongomodel/document/dynamic_finders_spec.rb +46 -46
  127. data/spec/mongomodel/document/finders_spec.rb +15 -15
  128. data/spec/mongomodel/document/indexes_spec.rb +29 -29
  129. data/spec/mongomodel/document/optimistic_locking_spec.rb +16 -16
  130. data/spec/mongomodel/document/persistence_spec.rb +39 -39
  131. data/spec/mongomodel/document/scopes_spec.rb +17 -17
  132. data/spec/mongomodel/document/validations/uniqueness_spec.rb +46 -46
  133. data/spec/mongomodel/document/validations_spec.rb +35 -35
  134. data/spec/mongomodel/document_spec.rb +19 -19
  135. data/spec/mongomodel/embedded_document_spec.rb +19 -19
  136. data/spec/mongomodel/mongomodel_spec.rb +7 -6
  137. data/spec/mongomodel/support/collection_spec.rb +54 -54
  138. data/spec/mongomodel/support/configuration_spec.rb +1 -1
  139. data/spec/mongomodel/support/map_spec.rb +66 -66
  140. data/spec/mongomodel/support/mongo_operator_spec.rb +5 -5
  141. data/spec/mongomodel/support/mongo_options_spec.rb +42 -42
  142. data/spec/mongomodel/support/mongo_order_spec.rb +24 -24
  143. data/spec/mongomodel/support/paginator_spec.rb +15 -15
  144. data/spec/mongomodel/support/property_spec.rb +29 -23
  145. data/spec/mongomodel/support/scope_spec.rb +205 -204
  146. data/spec/spec_helper.rb +13 -2
  147. data/spec/support/callbacks.rb +3 -8
  148. data/spec/support/helpers/define_class.rb +7 -7
  149. data/spec/support/helpers/document_finder_stubs.rb +6 -6
  150. data/spec/support/helpers/specs_for.rb +1 -1
  151. data/spec/support/helpers/validations.rb +1 -1
  152. data/spec/support/matchers/find_with.rb +8 -8
  153. data/spec/support/matchers/respond_to_boolean.rb +3 -3
  154. data/spec/support/matchers/run_callbacks.rb +6 -9
  155. data/spec/support/models.rb +5 -5
  156. metadata +23 -7
@@ -5,58 +5,58 @@ module MongoModel
5
5
  describe "generating attribute methods" do
6
6
  define_class(:TestDocument, described_class) do
7
7
  property :foo, String
8
-
8
+
9
9
  def foo(a); "from method"; end
10
10
  end
11
-
11
+
12
12
  subject { TestDocument.new }
13
-
13
+
14
14
  it "does not overwrite an existing method" do
15
15
  subject.foo(1).should == "from method"
16
16
  end
17
-
17
+
18
18
  context "on a subclass" do
19
19
  define_class(:SubDocument, :TestDocument)
20
20
  subject { SubDocument.new }
21
-
21
+
22
22
  it "does not overwrite methods defined on the superclass" do
23
23
  subject.foo(1).should == "from method"
24
24
  end
25
25
  end
26
-
26
+
27
27
  context "on a class with an included module" do
28
28
  module TestModule
29
29
  def foo(a); "from method"; end
30
30
  end
31
-
31
+
32
32
  it "does not overwrite methods defined on the included module" do
33
33
  TestDocument.send(:include, TestModule)
34
34
  subject.foo(1).should == "from method"
35
35
  end
36
36
  end
37
-
37
+
38
38
  context "on a class with an included concern that defines the property" do
39
39
  define_module(:TestConcern) do
40
40
  extend ActiveSupport::Concern
41
-
41
+
42
42
  included do
43
43
  property :bar, String
44
44
  end
45
-
45
+
46
46
  def bar(a); "from concern"; end
47
47
  end
48
-
48
+
49
49
  context "the base class" do
50
50
  it "does not overwrite methods defined within the concern" do
51
51
  TestDocument.send(:include, TestConcern)
52
52
  subject.bar(1).should == "from concern"
53
53
  end
54
54
  end
55
-
55
+
56
56
  context "subclasses" do
57
57
  define_class(:SubDocument, :TestDocument)
58
58
  subject { SubDocument.new }
59
-
59
+
60
60
  it "does not overwrite methods defined within the concern" do
61
61
  SubDocument.send(:include, TestConcern)
62
62
  subject.bar(1).should == "from concern"
@@ -16,109 +16,109 @@ module MongoModel
16
16
  Time => Types::Time.new.cast(Time.now),
17
17
  DateTime => Types::DateTime.new.cast(DateTime.now.in_time_zone)
18
18
  }
19
-
19
+
20
20
  specs_for(Document, EmbeddedDocument) do
21
21
  define_class(:TestDocument, described_class)
22
-
22
+
23
23
  it "has an attributes store on the instance" do
24
24
  doc = TestDocument.new
25
25
  doc.attributes.should be_an_instance_of(MongoModel::Attributes::Store)
26
26
  end
27
-
27
+
28
28
  it "converts to mongo representation" do
29
29
  doc = TestDocument.new
30
30
  doc.to_mongo.should == doc.attributes.to_mongo
31
31
  end
32
-
32
+
33
33
  AttributeTypes.each do |type, value|
34
34
  describe "setting #{type} attributes" do
35
35
  define_class(:TestDocument, described_class) do
36
36
  property :test_property, type
37
37
  end
38
-
38
+
39
39
  if specing?(EmbeddedDocument)
40
40
  define_class(:ParentDocument, Document) do
41
41
  property :child, TestDocument
42
42
  end
43
-
43
+
44
44
  let(:parent) { ParentDocument.create!(:child => TestDocument.new(:test_property => value)) }
45
45
  let(:child) { parent.child }
46
46
  let(:reloaded) { ParentDocument.find(parent.id).child }
47
-
47
+
48
48
  subject { child }
49
49
  else
50
50
  subject { TestDocument.create!(:test_property => value) }
51
-
51
+
52
52
  let(:reloaded) { TestDocument.find(subject.id) }
53
53
  end
54
-
54
+
55
55
  it "reads the correct value from attributes" do
56
56
  subject.test_property.should == value
57
57
  end
58
-
58
+
59
59
  it "reads the correct value after reloading" do
60
60
  reloaded.test_property.should == subject.test_property
61
61
  end
62
62
  end
63
63
  end
64
-
64
+
65
65
  it "has an attributes store" do
66
66
  doc = TestDocument.new
67
67
  doc.attributes.should be_an_instance_of(MongoModel::Attributes::Store)
68
68
  end
69
-
69
+
70
70
  it "duplicates attributes when duplicating object" do
71
71
  original = TestDocument.new
72
72
  duplicate = original.dup
73
-
73
+
74
74
  duplicate.attributes.should_not equal(original.attributes)
75
75
  end
76
-
76
+
77
77
  describe "initializing" do
78
78
  define_class(:Person, EmbeddedDocument) do
79
79
  property :name, String
80
80
  property :age, Integer, :default => 21
81
81
  end
82
-
82
+
83
83
  it "is initializable with attributes hash" do
84
84
  doc = Person.new(:name => 'Fred', :age => 42)
85
85
  doc.name.should == 'Fred'
86
86
  doc.age.should == 42
87
87
  end
88
-
88
+
89
89
  it "uses default attributes when initializing with partial attributes hash" do
90
90
  doc = Person.new(:name => 'Maurice')
91
91
  doc.age.should == 21
92
92
  end
93
-
93
+
94
94
  it "loads from mongo representation" do
95
95
  doc = Person.from_mongo({ 'name' => 'James', 'age' => 15 })
96
96
  doc.name.should == 'James'
97
97
  doc.age.should == 15
98
98
  end
99
99
  end
100
-
100
+
101
101
  describe "setting attributes with hash" do
102
102
  define_class(:TestDocument, described_class) do
103
103
  property :test_property, String
104
-
104
+
105
105
  def test_property=(value)
106
106
  write_attribute(:test_property, 'set from method')
107
107
  end
108
108
  end
109
-
109
+
110
110
  subject { TestDocument.new }
111
-
111
+
112
112
  it "calls custom property methods" do
113
113
  subject.attributes = { :test_property => 'property value' }
114
114
  subject.test_property.should == 'set from method'
115
115
  end
116
-
116
+
117
117
  it "uses write_attribute if no such property" do
118
118
  subject.attributes = { :non_property => 'property value' }
119
119
  subject.read_attribute(:non_property).should == 'property value'
120
120
  end
121
-
121
+
122
122
  if defined?(ActiveModel::ForbiddenAttributesProtection)
123
123
  it "raises ActiveModel::ForbiddenAttributesError when passed an unpermitted strong_params hash" do
124
124
  expect {
@@ -127,35 +127,35 @@ module MongoModel
127
127
  end
128
128
  end
129
129
  end
130
-
130
+
131
131
  describe "#new" do
132
132
  define_class(:TestDocument, described_class)
133
-
133
+
134
134
  it "yields the instance to a block if provided" do
135
135
  block_called = false
136
-
136
+
137
137
  TestDocument.new do |doc|
138
138
  block_called = true
139
139
  doc.should be_an_instance_of(TestDocument)
140
140
  end
141
-
142
- block_called.should be_true
141
+
142
+ block_called.should be true
143
143
  end
144
144
  end
145
-
145
+
146
146
  context "a frozen instance" do
147
147
  define_class(:TestDocument, described_class) do
148
148
  property :test_property, String
149
149
  end
150
-
150
+
151
151
  subject { TestDocument.new(:test_property => 'Test') }
152
-
152
+
153
153
  before(:each) { subject.freeze }
154
-
154
+
155
155
  it { should be_frozen }
156
-
156
+
157
157
  it "does not allow changes to the attributes hash" do
158
- lambda { subject.attributes[:test_property] = 'Change' }.should raise_error
158
+ lambda { subject.attributes[:test_property] = 'Change' }.should raise_error(RuntimeError)
159
159
  end
160
160
  end
161
161
  end
@@ -7,11 +7,11 @@ module MongoModel
7
7
  include MongoModel::CallbackHelpers
8
8
  property :name, String
9
9
  end
10
-
10
+
11
11
  define_class(:ParentDocument, Document) do
12
12
  property :things, Collection[ChildThingDocument]
13
13
  end
14
-
14
+
15
15
  it "calls callbacks on all embedded documents when adding a new one" do
16
16
  parent = ParentDocument.create!
17
17
  parent.things = Collection[ChildThingDocument].new
@@ -22,84 +22,88 @@ module MongoModel
22
22
  parent.save!
23
23
  end
24
24
  end
25
-
25
+
26
26
  describe "callbacks" do
27
27
  define_class(:ChildDocument, EmbeddedDocument) do
28
28
  include MongoModel::CallbackHelpers
29
29
  end
30
-
30
+
31
31
  define_class(:ParentDocument, Document) do
32
32
  property :child, ChildDocument
33
33
  end
34
-
34
+
35
35
  let(:child) { ChildDocument.new }
36
36
  let(:parent) { ParentDocument.create!(:child => child) }
37
-
37
+
38
38
  it "runs each type of callback when initializing" do
39
39
  instance = ChildDocument.new
40
40
  instance.should run_callbacks(:after_initialize)
41
41
  end
42
-
42
+
43
43
  it "runs each type of callback on find" do
44
44
  instance = ParentDocument.find(parent.id).child
45
45
  instance.should run_callbacks(:after_initialize, :after_find)
46
46
  end
47
-
47
+
48
48
  it "runs each type of callback when validating a new document" do
49
49
  instance = ChildDocument.new
50
50
  instance.valid?
51
51
  instance.should run_callbacks(:after_initialize, :before_validation, :after_validation)
52
52
  end
53
-
53
+
54
54
  it "runs each type of callback when validating an existing document" do
55
55
  instance = ParentDocument.find(parent.id).child
56
56
  instance.valid?
57
57
  instance.should run_callbacks(:after_initialize, :after_find, :before_validation, :after_validation)
58
58
  end
59
-
59
+
60
60
  it "runs each type of callback when creating a document" do
61
61
  instance = ParentDocument.create!(:child => ChildDocument.new)
62
62
  instance.child.should run_callbacks(:after_initialize, :before_validation, :after_validation, :before_save, :before_create, :after_create, :after_save)
63
63
  end
64
-
64
+
65
65
  it "runs each type of callback when saving an existing document" do
66
66
  instance = ParentDocument.find(parent.id)
67
67
  instance.save
68
68
  instance.child.should run_callbacks(:after_initialize, :after_find, :before_validation, :after_validation, :before_save, :before_update, :after_update, :after_save)
69
69
  end
70
-
70
+
71
71
  it "runs each type of callback when destroying a document" do
72
72
  instance = ParentDocument.find(parent.id)
73
73
  instance.destroy
74
74
  instance.child.should run_callbacks(:after_initialize, :after_find, :before_destroy, :after_destroy)
75
75
  end
76
-
76
+
77
77
  it "does not run destroy callbacks when deleting a document" do
78
78
  instance = ParentDocument.find(parent.id)
79
79
  instance.delete
80
80
  instance.child.should run_callbacks(:after_initialize, :after_find)
81
81
  end
82
82
  end
83
-
83
+
84
84
  [ :before_save, :before_create ].each do |callback|
85
- context "#{callback} callback return false" do
85
+ context "#{callback} callback halts" do
86
86
  define_class(:ChildDocument, EmbeddedDocument) do
87
- send(callback) { false }
87
+ if Gem::Version.new(ActiveSupport::VERSION::STRING) >= Gem::Version.new('5.0.0')
88
+ send(callback) { throw :abort }
89
+ else
90
+ send(callback) { false }
91
+ end
88
92
  end
89
-
93
+
90
94
  define_class(:ParentDocument, Document) do
91
95
  property :child, ChildDocument
92
96
  end
93
-
97
+
94
98
  let(:child) { ChildDocument.new }
95
99
  let(:parent) { ParentDocument.new(:child => child) }
96
-
100
+
97
101
  describe "#save" do
98
102
  it "returns false" do
99
- parent.save.should be_false
103
+ parent.save.should be false
100
104
  end
101
105
  end
102
-
106
+
103
107
  describe "#save!" do
104
108
  it "raises a MongoModel::DocumentNotSaved exception" do
105
109
  lambda { parent.save! }.should raise_error(MongoModel::DocumentNotSaved)
@@ -4,14 +4,16 @@ module MongoModel
4
4
  specs_for(Document, EmbeddedDocument) do
5
5
  describe "logging" do
6
6
  define_class(:TestDocument, described_class)
7
-
7
+
8
8
  let(:logger) { double('logger').as_null_object }
9
+
9
10
  before(:each) { MongoModel.logger = logger }
10
-
11
+ after(:each) { MongoModel.logger = nil }
12
+
11
13
  it "has a logger reader on the class" do
12
14
  TestDocument.logger.should == logger
13
15
  end
14
-
16
+
15
17
  it "has a logger reader on the instance" do
16
18
  TestDocument.new.logger.should == logger
17
19
  end
@@ -5,20 +5,20 @@ module MongoModel
5
5
  describe "counting tags" do
6
6
  # This example is extracted from the Counting Tags pattern in the
7
7
  # MongoDB Cookbook: http://cookbook.mongodb.org/patterns/count_tags/
8
-
8
+
9
9
  define_class(:Article, Document) do
10
10
  property :tags, Collection[String]
11
11
  end
12
-
12
+
13
13
  define_class(:Tag, Struct.new(:name, :count)) do
14
14
  include MongoModel::MapReduce
15
-
15
+
16
16
  self.parent_collection = Article.collection
17
-
17
+
18
18
  def initialize(name, count)
19
19
  super(name, count.to_i)
20
20
  end
21
-
21
+
22
22
  def self.map_function
23
23
  <<-MAP
24
24
  function() {
@@ -45,58 +45,58 @@ module MongoModel
45
45
  REDUCE
46
46
  end
47
47
  end
48
-
48
+
49
49
  specify "tag comparison" do
50
50
  Tag.new("Tag 1", 1).should == Tag.new("Tag 1", 1)
51
51
  Tag.new("Tag 2", 1).should_not == Tag.new("Tag 1", 1)
52
52
  Tag.new("Tag 1", 1).should_not == Tag.new("Tag 1", 2)
53
53
  end
54
-
54
+
55
55
  before do
56
56
  Article.create!(:tags => ["Tag 1", "Tag 2"])
57
57
  Article.create!(:tags => ["Tag 2"])
58
58
  Article.create!(:tags => ["Tag 3"])
59
59
  end
60
-
60
+
61
61
  it "has a default collection name based on the parent collection" do
62
62
  Tag.collection_name.should == "articles._tags"
63
63
  end
64
-
64
+
65
65
  it "stores the result in a named collection" do
66
66
  Tag.collection.name.should == Tag.collection_name
67
67
  end
68
-
68
+
69
69
  it "allows use of scope methods" do
70
70
  Tag.all.should == [Tag.new("Tag 1", 1), Tag.new("Tag 2", 2), Tag.new("Tag 3", 1)]
71
71
  Tag.order(:value.desc).first.should == Tag.new("Tag 2", 2)
72
72
  Tag.where(:value.gt => 1).should == [Tag.new("Tag 2", 2)]
73
73
  end
74
-
74
+
75
75
  it "loads previously computed results" do
76
76
  expected = Tag.all
77
77
  Article.create!(:tags => ["Tag 1"])
78
78
  Tag.cached.should == expected
79
79
  end
80
80
  end
81
-
81
+
82
82
  describe "pivot data" do
83
83
  # This example is similar to the Pivot Data pattern in the
84
84
  # MongoDB Cookbook: http://cookbook.mongodb.org/patterns/pivot/
85
-
85
+
86
86
  define_class(:Actor, Document) do
87
87
  property :name, String
88
88
  property :movies, Collection[String]
89
89
  end
90
-
90
+
91
91
  define_class(:Movie, Struct.new(:name, :actors)) do
92
92
  include MongoModel::MapReduce
93
-
93
+
94
94
  self.parent_collection = Actor.collection
95
-
95
+
96
96
  def self.from_mongo(attrs)
97
97
  new(attrs['_id'], attrs['value']['actors'].sort)
98
98
  end
99
-
99
+
100
100
  def self.map_function
101
101
  <<-MAP
102
102
  function() {
@@ -121,12 +121,12 @@ module MongoModel
121
121
  REDUCE
122
122
  end
123
123
  end
124
-
124
+
125
125
  before do
126
126
  Actor.create!(:name => "Richard Gere", :movies => ['Pretty Woman', 'Runaway Bride', 'Chicago'])
127
127
  Actor.create!(:name => "Julia Roberts", :movies => ['Pretty Woman', 'Runaway Bride', 'Erin Brockovich'])
128
128
  end
129
-
129
+
130
130
  it "pivots data" do
131
131
  Movie.all.should include(
132
132
  Movie.new("Pretty Woman", ["Julia Roberts", "Richard Gere"]),