mongoid-paranoia 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 +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