mongoid-versioning 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (195) hide show
  1. data/.gitignore +25 -0
  2. data/CHANGELOG.md +2 -0
  3. data/Gemfile +7 -0
  4. data/README.md +73 -0
  5. data/Rakefile +7 -0
  6. data/lib/mongoid/versioning.rb +217 -0
  7. data/lib/mongoid/versioning/version.rb +5 -0
  8. data/mongoid-versioning.gemspec +18 -0
  9. data/spec/app/models/account.rb +32 -0
  10. data/spec/app/models/acolyte.rb +16 -0
  11. data/spec/app/models/actor.rb +19 -0
  12. data/spec/app/models/actor_observer.rb +15 -0
  13. data/spec/app/models/actress.rb +2 -0
  14. data/spec/app/models/address.rb +72 -0
  15. data/spec/app/models/address_component.rb +5 -0
  16. data/spec/app/models/address_number.rb +6 -0
  17. data/spec/app/models/agency.rb +5 -0
  18. data/spec/app/models/agent.rb +12 -0
  19. data/spec/app/models/album.rb +14 -0
  20. data/spec/app/models/alert.rb +5 -0
  21. data/spec/app/models/animal.rb +25 -0
  22. data/spec/app/models/answer.rb +4 -0
  23. data/spec/app/models/appointment.rb +7 -0
  24. data/spec/app/models/article.rb +13 -0
  25. data/spec/app/models/artist.rb +66 -0
  26. data/spec/app/models/artwork.rb +4 -0
  27. data/spec/app/models/augmentation.rb +11 -0
  28. data/spec/app/models/author.rb +6 -0
  29. data/spec/app/models/band.rb +25 -0
  30. data/spec/app/models/bar.rb +9 -0
  31. data/spec/app/models/basic.rb +6 -0
  32. data/spec/app/models/bed.rb +1 -0
  33. data/spec/app/models/big_palette.rb +2 -0
  34. data/spec/app/models/birthday.rb +13 -0
  35. data/spec/app/models/book.rb +12 -0
  36. data/spec/app/models/breed.rb +4 -0
  37. data/spec/app/models/browser.rb +6 -0
  38. data/spec/app/models/building.rb +7 -0
  39. data/spec/app/models/building_address.rb +7 -0
  40. data/spec/app/models/bus.rb +7 -0
  41. data/spec/app/models/business.rb +5 -0
  42. data/spec/app/models/callback_recorder.rb +25 -0
  43. data/spec/app/models/callback_test.rb +9 -0
  44. data/spec/app/models/canvas.rb +25 -0
  45. data/spec/app/models/car.rb +1 -0
  46. data/spec/app/models/cat.rb +8 -0
  47. data/spec/app/models/category.rb +8 -0
  48. data/spec/app/models/child.rb +4 -0
  49. data/spec/app/models/child_doc.rb +22 -0
  50. data/spec/app/models/church.rb +4 -0
  51. data/spec/app/models/circle.rb +3 -0
  52. data/spec/app/models/circuit.rb +4 -0
  53. data/spec/app/models/circus.rb +7 -0
  54. data/spec/app/models/code.rb +5 -0
  55. data/spec/app/models/comment.rb +16 -0
  56. data/spec/app/models/contractor.rb +7 -0
  57. data/spec/app/models/cookie.rb +6 -0
  58. data/spec/app/models/country_code.rb +8 -0
  59. data/spec/app/models/definition.rb +7 -0
  60. data/spec/app/models/description.rb +11 -0
  61. data/spec/app/models/dictionary.rb +10 -0
  62. data/spec/app/models/division.rb +10 -0
  63. data/spec/app/models/doctor.rb +12 -0
  64. data/spec/app/models/dog.rb +6 -0
  65. data/spec/app/models/dokument.rb +5 -0
  66. data/spec/app/models/driver.rb +7 -0
  67. data/spec/app/models/drug.rb +8 -0
  68. data/spec/app/models/email.rb +6 -0
  69. data/spec/app/models/employer.rb +5 -0
  70. data/spec/app/models/entry.rb +6 -0
  71. data/spec/app/models/eraser.rb +1 -0
  72. data/spec/app/models/event.rb +22 -0
  73. data/spec/app/models/exhibition.rb +4 -0
  74. data/spec/app/models/exhibitor.rb +5 -0
  75. data/spec/app/models/eye.rb +9 -0
  76. data/spec/app/models/eye_bowl.rb +9 -0
  77. data/spec/app/models/face.rb +8 -0
  78. data/spec/app/models/favorite.rb +6 -0
  79. data/spec/app/models/filesystem.rb +4 -0
  80. data/spec/app/models/firefox.rb +4 -0
  81. data/spec/app/models/fish.rb +8 -0
  82. data/spec/app/models/folder.rb +7 -0
  83. data/spec/app/models/folder_item.rb +9 -0
  84. data/spec/app/models/fruits.rb +28 -0
  85. data/spec/app/models/game.rb +21 -0
  86. data/spec/app/models/ghost.rb +7 -0
  87. data/spec/app/models/home.rb +4 -0
  88. data/spec/app/models/house.rb +8 -0
  89. data/spec/app/models/html_writer.rb +3 -0
  90. data/spec/app/models/image.rb +22 -0
  91. data/spec/app/models/implant.rb +16 -0
  92. data/spec/app/models/item.rb +12 -0
  93. data/spec/app/models/jar.rb +7 -0
  94. data/spec/app/models/label.rb +40 -0
  95. data/spec/app/models/language.rb +5 -0
  96. data/spec/app/models/lat_lng.rb +15 -0
  97. data/spec/app/models/league.rb +11 -0
  98. data/spec/app/models/learner.rb +2 -0
  99. data/spec/app/models/line_item.rb +6 -0
  100. data/spec/app/models/location.rb +8 -0
  101. data/spec/app/models/login.rb +8 -0
  102. data/spec/app/models/manufacturer.rb +7 -0
  103. data/spec/app/models/meat.rb +4 -0
  104. data/spec/app/models/membership.rb +4 -0
  105. data/spec/app/models/mixed_drink.rb +4 -0
  106. data/spec/app/models/movie.rb +12 -0
  107. data/spec/app/models/my_hash.rb +2 -0
  108. data/spec/app/models/name.rb +23 -0
  109. data/spec/app/models/node.rb +5 -0
  110. data/spec/app/models/note.rb +12 -0
  111. data/spec/app/models/ordered_post.rb +6 -0
  112. data/spec/app/models/ordered_preference.rb +6 -0
  113. data/spec/app/models/oscar.rb +15 -0
  114. data/spec/app/models/override.rb +16 -0
  115. data/spec/app/models/ownable.rb +6 -0
  116. data/spec/app/models/owner.rb +6 -0
  117. data/spec/app/models/page.rb +5 -0
  118. data/spec/app/models/page_question.rb +4 -0
  119. data/spec/app/models/palette.rb +7 -0
  120. data/spec/app/models/paranoid_phone.rb +25 -0
  121. data/spec/app/models/paranoid_post.rb +36 -0
  122. data/spec/app/models/parent.rb +5 -0
  123. data/spec/app/models/parent_doc.rb +6 -0
  124. data/spec/app/models/passport.rb +5 -0
  125. data/spec/app/models/patient.rb +9 -0
  126. data/spec/app/models/pdf_writer.rb +3 -0
  127. data/spec/app/models/pencil.rb +1 -0
  128. data/spec/app/models/person.rb +200 -0
  129. data/spec/app/models/pet.rb +23 -0
  130. data/spec/app/models/pet_owner.rb +6 -0
  131. data/spec/app/models/phone.rb +11 -0
  132. data/spec/app/models/phone_observer.rb +6 -0
  133. data/spec/app/models/pizza.rb +7 -0
  134. data/spec/app/models/player.rb +35 -0
  135. data/spec/app/models/post.rb +42 -0
  136. data/spec/app/models/powerup.rb +11 -0
  137. data/spec/app/models/preference.rb +9 -0
  138. data/spec/app/models/princess.rb +8 -0
  139. data/spec/app/models/product.rb +15 -0
  140. data/spec/app/models/profile.rb +5 -0
  141. data/spec/app/models/pronunciation.rb +5 -0
  142. data/spec/app/models/purchase.rb +4 -0
  143. data/spec/app/models/question.rb +8 -0
  144. data/spec/app/models/quiz.rb +10 -0
  145. data/spec/app/models/rating.rb +8 -0
  146. data/spec/app/models/record.rb +46 -0
  147. data/spec/app/models/registry.rb +4 -0
  148. data/spec/app/models/role.rb +5 -0
  149. data/spec/app/models/root_category.rb +4 -0
  150. data/spec/app/models/sandwich.rb +4 -0
  151. data/spec/app/models/scheduler.rb +7 -0
  152. data/spec/app/models/seo.rb +7 -0
  153. data/spec/app/models/series.rb +4 -0
  154. data/spec/app/models/server.rb +13 -0
  155. data/spec/app/models/service.rb +22 -0
  156. data/spec/app/models/shape.rb +12 -0
  157. data/spec/app/models/shelf.rb +5 -0
  158. data/spec/app/models/shipping_container.rb +5 -0
  159. data/spec/app/models/shop.rb +6 -0
  160. data/spec/app/models/short_agent.rb +4 -0
  161. data/spec/app/models/short_quiz.rb +5 -0
  162. data/spec/app/models/slave.rb +6 -0
  163. data/spec/app/models/song.rb +8 -0
  164. data/spec/app/models/square.rb +4 -0
  165. data/spec/app/models/strategy.rb +3 -0
  166. data/spec/app/models/sub_item.rb +3 -0
  167. data/spec/app/models/survey.rb +5 -0
  168. data/spec/app/models/symptom.rb +6 -0
  169. data/spec/app/models/tag.rb +8 -0
  170. data/spec/app/models/target.rb +5 -0
  171. data/spec/app/models/template.rb +5 -0
  172. data/spec/app/models/thing.rb +9 -0
  173. data/spec/app/models/title.rb +4 -0
  174. data/spec/app/models/tool.rb +8 -0
  175. data/spec/app/models/topping.rb +5 -0
  176. data/spec/app/models/track.rb +38 -0
  177. data/spec/app/models/translation.rb +5 -0
  178. data/spec/app/models/tree.rb +9 -0
  179. data/spec/app/models/truck.rb +3 -0
  180. data/spec/app/models/user.rb +20 -0
  181. data/spec/app/models/user_account.rb +10 -0
  182. data/spec/app/models/validation_callback.rb +10 -0
  183. data/spec/app/models/vehicle.rb +11 -0
  184. data/spec/app/models/version.rb +5 -0
  185. data/spec/app/models/vet_visit.rb +5 -0
  186. data/spec/app/models/video.rb +17 -0
  187. data/spec/app/models/weapon.rb +11 -0
  188. data/spec/app/models/wiki_page.rb +17 -0
  189. data/spec/app/models/word.rb +12 -0
  190. data/spec/app/models/word_origin.rb +11 -0
  191. data/spec/app/models/writer.rb +11 -0
  192. data/spec/config/mongoid.yml +40 -0
  193. data/spec/mongoid/versioning_spec.rb +540 -0
  194. data/spec/spec_helper.rb +80 -0
  195. metadata +271 -0
data/.gitignore ADDED
@@ -0,0 +1,25 @@
1
+ # Because this is a gem, ignore Gemfile.lock:
2
+
3
+ Gemfile.lock
4
+
5
+ # And because this is Ruby, ignore the following
6
+ # (source: https://github.com/github/gitignore/blob/master/Ruby.gitignore):
7
+
8
+ *.gem
9
+ *.rbc
10
+ .bundle
11
+ .config
12
+ coverage
13
+ InstalledFiles
14
+ lib/bundler/man
15
+ pkg
16
+ rdoc
17
+ spec/reports
18
+ test/tmp
19
+ test/version_tmp
20
+ tmp
21
+
22
+ # YARD artifacts
23
+ .yardoc
24
+ _yardoc
25
+ doc/
data/CHANGELOG.md ADDED
@@ -0,0 +1,2 @@
1
+ # 0.1.0 (February 26, 2013)
2
+ * First public version.
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ ruby '1.9.3'
2
+ source 'https://rubygems.org'
3
+
4
+ gemspec
5
+
6
+ gem 'rspec'
7
+ gem 'rake'
data/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # mongoid-versioning
2
+
3
+ Mongoid supports simple versioning through inclusion of the `Mongoid::Versioning` module. Including this module will create a versions embedded relation on the document that it will append to on each save. It will also update the version number on the document, which is an integer.
4
+
5
+ ## Installation
6
+
7
+ In your Gemfile:
8
+
9
+ ```ruby
10
+ gem 'mongoid-versioning'
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```ruby
16
+ class Person
17
+ include Mongoid::Document
18
+ include Mongoid::Versioning
19
+ end
20
+ ```
21
+
22
+ You can also set a `max_versions` setting, and Mongoid will only keep the max most recent versions.
23
+
24
+ ```ruby
25
+ class Person
26
+ include Mongoid::Document
27
+ include Mongoid::Versioning
28
+
29
+ # keep at most 5 versions of a record
30
+ max_versions 5
31
+ end
32
+ ```
33
+
34
+ You may skip versioning at any point in time by wrapping the persistence call in a `versionless` block.
35
+
36
+ ```ruby
37
+ person.versionless do |doc|
38
+ doc.update_attributes(name: "Theodore")
39
+ end
40
+ ```
41
+
42
+ ## Contributing
43
+
44
+ 1. Fork it
45
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
46
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
47
+ 4. Push to the branch (`git push origin my-new-feature`)
48
+ 5. Create new Pull Request
49
+
50
+ ## Copyright
51
+
52
+ (The MIT license)
53
+
54
+ Copyright (c) 2013 Mario Uher
55
+
56
+ Permission is hereby granted, free of charge, to any person obtaining
57
+ a copy of this software and associated documentation files (the
58
+ "Software"), to deal in the Software without restriction, including
59
+ without limitation the rights to use, copy, modify, merge, publish,
60
+ distribute, sublicense, and/or sell copies of the Software, and to
61
+ permit persons to whom the Software is furnished to do so, subject to
62
+ the following conditions:
63
+
64
+ The above copyright notice and this permission notice shall be
65
+ included in all copies or substantial portions of the Software.
66
+
67
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
68
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
69
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
70
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
71
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
72
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
73
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.test_files = FileList['spec/**/*_spec.rb']
5
+ end
6
+
7
+ task default: :test
@@ -0,0 +1,217 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+
4
+ # Include this module to get automatic versioning of root level documents.
5
+ # This will add a version field to the +Document+ and a has_many association
6
+ # with all the versions contained in it.
7
+ module Versioning
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ field :version, type: Integer, default: 1
12
+
13
+ embeds_many \
14
+ :versions,
15
+ class_name: self.name,
16
+ validate: false,
17
+ cyclic: true,
18
+ inverse_of: nil,
19
+ versioned: true
20
+
21
+ set_callback :save, :before, :revise, if: :revisable?
22
+
23
+ class_attribute :version_max
24
+ self.cyclic = true
25
+ end
26
+
27
+ # Create a new version of the +Document+. This will load the previous
28
+ # document from the database and set it as the next version before saving
29
+ # the current document. It then increments the version number. If a #max_versions
30
+ # limit is set in the model and it's exceeded, the oldest version gets discarded.
31
+ #
32
+ # @example Revise the document.
33
+ # person.revise
34
+ #
35
+ # @since 1.0.0
36
+ def revise
37
+ previous = previous_revision
38
+ if previous && versioned_attributes_changed?
39
+ new_version = versions.build(
40
+ previous.versioned_attributes, without_protection: true
41
+ )
42
+ new_version._id = nil
43
+ if version_max.present? && versions.length > version_max
44
+ deleted = versions.first
45
+ if deleted.paranoid?
46
+ versions.delete_one(deleted)
47
+ collection.find(atomic_selector).
48
+ update({ "$pull" => { "versions" => { "version" => deleted.version }}})
49
+ else
50
+ versions.delete(deleted)
51
+ end
52
+ end
53
+ self.version = (version || 1 ) + 1
54
+ end
55
+ end
56
+
57
+ # Forces the creation of a new version of the +Document+, regardless of
58
+ # whether a change was actually made.
59
+ #
60
+ # @example Revise the document.
61
+ # person.revise!
62
+ #
63
+ # @since 2.2.1
64
+ def revise!
65
+ versions.build(
66
+ (previous_revision || self).versioned_attributes, without_protection: true
67
+ )
68
+ versions.shift if version_max.present? && versions.length > version_max
69
+ self.version = (version || 1 ) + 1
70
+ save
71
+ end
72
+
73
+ # Filters the results of +changes+ by removing any fields that should
74
+ # not be versioned.
75
+ #
76
+ # @return [ Hash ] A hash of versioned changed attributes.
77
+ #
78
+ # @since 2.1.0
79
+ def versioned_changes
80
+ only_versioned_attributes(changes.except("updated_at"))
81
+ end
82
+
83
+ # Filters the results of +attributes+ by removing any fields that should
84
+ # not be versioned.
85
+ #
86
+ # @return [ Hash ] A hash of versioned attributes.
87
+ #
88
+ # @since 2.1.0
89
+ def versioned_attributes
90
+ only_versioned_attributes(attributes)
91
+ end
92
+
93
+ # Check if any versioned fields have been modified. This is similar
94
+ # to +changed?+, except this method also ignores fields set to be
95
+ # ignored by versioning.
96
+ #
97
+ # @return [ Boolean ] Whether fields that will be versioned have changed.
98
+ #
99
+ # @since 2.1.0
100
+ def versioned_attributes_changed?
101
+ !versioned_changes.empty?
102
+ end
103
+
104
+ # Executes a block that temporarily disables versioning. This is for cases
105
+ # where you do not want to version on every save.
106
+ #
107
+ # @example Execute a save without versioning.
108
+ # person.versionless(&:save)
109
+ #
110
+ # @return [ Object ] The document or result of the block execution.
111
+ #
112
+ # @since 2.0.0
113
+ def versionless
114
+ @versionless = true
115
+ result = yield(self) if block_given?
116
+ @versionless = false
117
+ result || self
118
+ end
119
+
120
+ private
121
+
122
+ # Find the previous version of this document in the database, or if the
123
+ # document had been saved without versioning return the persisted one.
124
+ #
125
+ # @example Find the last version.
126
+ # document.find_last_version
127
+ #
128
+ # @return [ Document, nil ] The previously saved document.
129
+ #
130
+ # @since 2.0.0
131
+ def previous_revision
132
+ _loading_revision do
133
+ self.class.unscoped.
134
+ where(_id: id).
135
+ any_of({ version: version }, { version: nil }).first
136
+ end
137
+ end
138
+
139
+ # Is the document able to be revised? This is true if the document has
140
+ # changed and we have not explicitly told it not to version.
141
+ #
142
+ # @example Is the document revisable?
143
+ # document.revisable?
144
+ #
145
+ # @return [ true, false ] If the document is revisable.
146
+ #
147
+ # @since 2.0.0
148
+ def revisable?
149
+ versioned_attributes_changed? && !versionless?
150
+ end
151
+
152
+ # Are we in versionless mode? This is true if in a versionless block on the
153
+ # document.
154
+ #
155
+ # @example Is the document in versionless mode?
156
+ # document.versionless?
157
+ #
158
+ # @return [ true, false ] Is the document not currently versioning.
159
+ #
160
+ # @since 2.0.0
161
+ def versionless?
162
+ @versionless ||= false
163
+ end
164
+
165
+ # Filters fields that should not be versioned out of an attributes hash.
166
+ # Dynamic attributes are always versioned.
167
+ #
168
+ # @param [ Hash ] A hash with field names as keys.
169
+ #
170
+ # @return [ Hash ] The hash without non-versioned columns.
171
+ #
172
+ # @since 2.1.0
173
+ def only_versioned_attributes(hash)
174
+ versioned = {}
175
+ hash.except("versions").each_pair do |name, value|
176
+ add_versioned_attribute(versioned, name, value)
177
+ end
178
+ versioned
179
+ end
180
+
181
+ # Add the versioned attribute. Will work now for localized fields.
182
+ #
183
+ # @api private
184
+ #
185
+ # @example Add the versioned attribute.
186
+ # model.add_versioned_attribute({}, "name", "test")
187
+ #
188
+ # @param [ Hash ] versioned The versioned attributes.
189
+ # @param [ String ] name The name of the field.
190
+ # @param [ Object ] value The value for the field.
191
+ #
192
+ # @since 3.0.10
193
+ def add_versioned_attribute(versioned, name, value)
194
+ field = fields[name]
195
+ if field && field.localized?
196
+ versioned["#{name}_translations"] = value
197
+ else
198
+ versioned[name] = value if !field || field.versioned?
199
+ end
200
+ end
201
+
202
+ module ClassMethods
203
+
204
+ # Sets the maximum number of versions to store.
205
+ #
206
+ # @example Set the maximum.
207
+ # Person.max_versions(5)
208
+ #
209
+ # @param [ Integer ] number The maximum number to store.
210
+ #
211
+ # @return [ Integer ] The max number of versions.
212
+ def max_versions(number)
213
+ self.version_max = number.to_i
214
+ end
215
+ end
216
+ end
217
+ end
@@ -0,0 +1,5 @@
1
+ module Mongoid
2
+ module Versioning
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,18 @@
1
+ $: << File.expand_path('../lib', __FILE__)
2
+ require 'mongoid/versioning/version'
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = 'mongoid-versioning'
6
+ gem.version = Mongoid::Versioning::VERSION
7
+ gem.authors = 'Mario Uher'
8
+ gem.email = 'uher.mario@gmail.com'
9
+ gem.homepage = 'https://github.com/haihappen/mongoid-versioning'
10
+ gem.summary = 'Extraction of mongoid-versioning into its own gem.'
11
+ gem.description = "Mongoid supports simple versioning through inclusion of the Mongoid::Versioning module."
12
+
13
+ gem.files = `git ls-files`.split("\n")
14
+ gem.require_path = 'lib'
15
+
16
+ gem.add_dependency 'activesupport'
17
+ gem.add_dependency 'mongoid'
18
+ end
@@ -0,0 +1,32 @@
1
+ class Account
2
+ include Mongoid::Document
3
+
4
+ field :_id, type: String, default: ->{ name.try(:parameterize) }
5
+
6
+ field :number, type: String
7
+ field :balance, type: String
8
+ field :nickname, type: String
9
+ field :name, type: String
10
+ field :balanced, type: Boolean, default: ->{ balance? ? true : false }
11
+
12
+ field :overridden, type: String
13
+
14
+ embeds_many :memberships
15
+ belongs_to :creator, class_name: "User", foreign_key: :creator_id
16
+ belongs_to :person
17
+ has_many :alerts
18
+ has_and_belongs_to_many :agents
19
+ has_one :comment, validate: false
20
+
21
+ attr_accessible :nickname, as: [ :default, :admin ]
22
+ attr_accessible :name, as: [ :default, :admin ]
23
+ attr_accessible :balance, as: :default
24
+
25
+ validates_presence_of :name
26
+ validates_presence_of :nickname, on: :upsert
27
+ validates_length_of :name, maximum: 10, on: :create
28
+
29
+ def overridden
30
+ self[:overridden] = "not recommended"
31
+ end
32
+ end
@@ -0,0 +1,16 @@
1
+ class Acolyte
2
+ include Mongoid::Document
3
+ field :status
4
+ field :name
5
+
6
+ embeds_many :versions, as: :memorable
7
+ belongs_to :church
8
+
9
+ default_scope asc(:name)
10
+ scope :active, ->{ where(status: "active") }
11
+ scope :named, ->{ where(:name.exists => true) }
12
+
13
+ def callback_test?
14
+ name == "callback-test"
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ class Actor
2
+ include Mongoid::Document
3
+ field :name
4
+ field :after_custom_count, type: Integer, default: 0
5
+ has_and_belongs_to_many :tags
6
+ embeds_many :things, validate: false, cascade_callbacks: true
7
+ accepts_nested_attributes_for :things, allow_destroy: true
8
+
9
+ define_model_callbacks :custom
10
+ observable :custom
11
+
12
+ def do_something
13
+ run_callbacks(:custom) do
14
+ self.name = "custom"
15
+ end
16
+ end
17
+ end
18
+
19
+ require "app/models/actress"
@@ -0,0 +1,15 @@
1
+ class ActorObserver < Mongoid::Observer
2
+ attr_reader :last_after_create_record
3
+
4
+ def after_create(record)
5
+ @last_after_create_record = record
6
+ end
7
+
8
+ def after_custom(record)
9
+ record.after_custom_count += 1
10
+ end
11
+
12
+ def before_custom(record)
13
+ @after_custom_called = true
14
+ end
15
+ end