mongoid-paranoia 0.1.0

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 (195) hide show
  1. data/.gitignore +25 -0
  2. data/CHANGELOG.md +4 -0
  3. data/Gemfile +7 -0
  4. data/README.md +65 -0
  5. data/Rakefile +7 -0
  6. data/lib/mongoid/paranoia.rb +133 -0
  7. data/lib/mongoid/paranoia/version.rb +5 -0
  8. data/mongoid-paranoia.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/paranoia_spec.rb +715 -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,4 @@
1
+
2
+
3
+ # 0.1.0 (February 26, 2013)
4
+ * 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,65 @@
1
+ # mongoid-paranoia
2
+
3
+ There may be times when you don't want documents to actually get deleted from the database, but "flagged" as deleted. Mongoid provides a Paranoia module to give you just that.
4
+
5
+ ## Installation
6
+
7
+ In your Gemfile:
8
+
9
+ ```ruby
10
+ gem 'mongoid-paranoia'
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```ruby
16
+ class Person
17
+ include Mongoid::Document
18
+ include Mongoid::Paranoia
19
+ end
20
+
21
+ person.delete # Sets the deleted_at field to the current time, ignoring callbacks.
22
+ person.delete! # Permanently deletes the document, ignoring callbacks.
23
+ person.destroy # Sets the deleted_at field to the current time, firing callbacks.
24
+ person.destroy! # Permanently deletes the document, firing callbacks.
25
+ person.restore # Brings the "deleted" document back to life.
26
+ ```
27
+
28
+ The documents that have been "flagged" as deleted (soft deleted) can be accessed at any time by calling the deleted class method on the class.
29
+
30
+ ```ruby
31
+ Person.deleted # Returns documents that have been "flagged" as deleted.
32
+ ```
33
+
34
+ ## Contributing
35
+
36
+ 1. Fork it
37
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
38
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
39
+ 4. Push to the branch (`git push origin my-new-feature`)
40
+ 5. Create new Pull Request
41
+
42
+ ## Copyright
43
+
44
+ (The MIT license)
45
+
46
+ Copyright (c) 2013 Mario Uher
47
+
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of this software and associated documentation files (the
50
+ "Software"), to deal in the Software without restriction, including
51
+ without limitation the rights to use, copy, modify, merge, publish,
52
+ distribute, sublicense, and/or sell copies of the Software, and to
53
+ permit persons to whom the Software is furnished to do so, subject to
54
+ the following conditions:
55
+
56
+ The above copyright notice and this permission notice shall be
57
+ included in all copies or substantial portions of the Software.
58
+
59
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
60
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
61
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
62
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
63
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
64
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
65
+ 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,133 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+
4
+ # Include this module to get soft deletion of root level documents.
5
+ # This will add a deleted_at field to the +Document+, managed automatically.
6
+ # Potentially incompatible with unique indices. (if collisions with deleted items)
7
+ #
8
+ # @example Make a document paranoid.
9
+ # class Person
10
+ # include Mongoid::Document
11
+ # include Mongoid::Paranoia
12
+ # end
13
+ module Paranoia
14
+ extend ActiveSupport::Concern
15
+
16
+ included do
17
+ field :deleted_at, type: Time
18
+ self.paranoid = true
19
+
20
+ default_scope where(deleted_at: nil)
21
+ scope :deleted, ne(deleted_at: nil)
22
+ end
23
+
24
+ # Delete the paranoid +Document+ from the database completely. This will
25
+ # run the destroy callbacks.
26
+ #
27
+ # @example Hard destroy the document.
28
+ # document.destroy!
29
+ #
30
+ # @return [ true, false ] If the operation succeeded.
31
+ #
32
+ # @since 1.0.0
33
+ def destroy!
34
+ run_callbacks(:destroy) { delete! }
35
+ end
36
+
37
+ # Delete the paranoid +Document+ from the database completely.
38
+ #
39
+ # @example Hard delete the document.
40
+ # document.delete!
41
+ #
42
+ # @return [ true, false ] If the operation succeeded.
43
+ #
44
+ # @since 1.0.0
45
+ def delete!
46
+ Persistence::Operations.remove(self).persist
47
+ end
48
+
49
+ # Delete the +Document+, will set the deleted_at timestamp and not actually
50
+ # delete it.
51
+ #
52
+ # @example Soft remove the document.
53
+ # document.remove
54
+ #
55
+ # @param [ Hash ] options The database options.
56
+ #
57
+ # @return [ true ] True.
58
+ #
59
+ # @since 1.0.0
60
+ def remove(options = {})
61
+ cascade!
62
+ time = self.deleted_at = Time.now
63
+ paranoid_collection.find(atomic_selector).
64
+ update({ "$set" => { paranoid_field => time }})
65
+ @destroyed = true
66
+ IdentityMap.remove(self)
67
+ Threaded.clear_options!
68
+ true
69
+ end
70
+ alias :delete :remove
71
+
72
+ # Determines if this document is destroyed.
73
+ #
74
+ # @example Is the document destroyed?
75
+ # person.destroyed?
76
+ #
77
+ # @return [ true, false ] If the document is destroyed.
78
+ #
79
+ # @since 1.0.0
80
+ def destroyed?
81
+ (@destroyed ||= false) || !!deleted_at
82
+ end
83
+ alias :deleted? :destroyed?
84
+
85
+ # Restores a previously soft-deleted document. Handles this by removing the
86
+ # deleted_at flag.
87
+ #
88
+ # @example Restore the document from deleted state.
89
+ # document.restore
90
+ #
91
+ # @return [ Time ] The time the document had been deleted.
92
+ #
93
+ # @since 1.0.0
94
+ def restore
95
+ paranoid_collection.find(atomic_selector).
96
+ update({ "$unset" => { paranoid_field => true }})
97
+ attributes.delete("deleted_at")
98
+ @destroyed = false
99
+ true
100
+ end
101
+
102
+ # Returns a string representing the documents's key suitable for use in URLs.
103
+ def to_param
104
+ new_record? ? nil : to_key.join('-')
105
+ end
106
+
107
+ private
108
+
109
+ # Get the collection to be used for paranoid operations.
110
+ #
111
+ # @example Get the paranoid collection.
112
+ # document.paranoid_collection
113
+ #
114
+ # @return [ Collection ] The root collection.
115
+ #
116
+ # @since 2.3.1
117
+ def paranoid_collection
118
+ embedded? ? _root.collection : self.collection
119
+ end
120
+
121
+ # Get the field to be used for paranoid operations.
122
+ #
123
+ # @example Get the paranoid field.
124
+ # document.paranoid_field
125
+ #
126
+ # @return [ String ] The deleted at field.
127
+ #
128
+ # @since 2.3.1
129
+ def paranoid_field
130
+ embedded? ? "#{atomic_position}.deleted_at" : "deleted_at"
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,5 @@
1
+ module Mongoid
2
+ module Paranoia
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,18 @@
1
+ $: << File.expand_path('../lib', __FILE__)
2
+ require 'mongoid/paranoia/version'
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = 'mongoid-paranoia'
6
+ gem.version = Mongoid::Paranoia::VERSION
7
+ gem.authors = 'Mario Uher'
8
+ gem.email = 'uher.mario@gmail.com'
9
+ gem.homepage = 'https://github.com/haihappen/mongoid-paranoia'
10
+ gem.summary = 'Extraction of mongoid-paranoia into its own gem.'
11
+ gem.description = "There may be times when you don't want documents to actually get deleted from the database, but \"flagged\" as deleted."
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
@@ -0,0 +1,2 @@
1
+ class Actress < Actor
2
+ end
@@ -0,0 +1,72 @@
1
+ class Address
2
+ include Mongoid::Document
3
+
4
+ field :_id, type: String, default: ->{ street.try(:parameterize) }
5
+
6
+ attr_accessor :mode
7
+
8
+ field :address_type
9
+ field :number, type: Integer
10
+ field :street
11
+ field :city
12
+ field :state
13
+ field :post_code
14
+ field :parent_title
15
+ field :services, type: Array
16
+ field :latlng, type: Array
17
+ field :map, type: Hash
18
+ field :move_in, type: DateTime
19
+ field :s, type: String, as: :suite
20
+ field :name, localize: true
21
+
22
+ embeds_many :locations, validate: false
23
+ embeds_one :code, validate: false
24
+ embeds_one :target, as: :targetable, validate: false
25
+
26
+ embedded_in :addressable, polymorphic: true do
27
+ def extension
28
+ "Testing"
29
+ end
30
+ def doctor?
31
+ title == "Dr"
32
+ end
33
+ end
34
+
35
+ accepts_nested_attributes_for :code, :target
36
+ accepts_nested_attributes_for :locations, allow_destroy: true
37
+
38
+ belongs_to :account
39
+ belongs_to :band
40
+
41
+ scope :without_postcode, where(postcode: nil)
42
+ scope :rodeo, where(street: "Rodeo Dr") do
43
+ def mansion?
44
+ all? { |address| address.street == "Rodeo Dr" }
45
+ end
46
+ end
47
+
48
+ validates_presence_of :street, on: :update
49
+ validates_format_of :street, with: /\D/, allow_nil: true
50
+
51
+ def set_parent=(set = false)
52
+ self.parent_title = addressable.title if set
53
+ end
54
+
55
+ def <=>(other)
56
+ street <=> other.street
57
+ end
58
+
59
+ class << self
60
+ def california
61
+ where(state: "CA")
62
+ end
63
+
64
+ def homes
65
+ where(address_type: "Home")
66
+ end
67
+
68
+ def streets
69
+ all.map(&:street)
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,5 @@
1
+ class AddressComponent
2
+ include Mongoid::Document
3
+ field :street, type: String
4
+ embedded_in :person
5
+ end