mongoid-paranoia 0.3.0 → 1.0.0.beta1

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 (45) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +1 -0
  3. data/Gemfile +2 -0
  4. data/Rakefile +3 -5
  5. data/gemfiles/mongoid_master.gemfile +2 -1
  6. data/lib/mongoid/core_ext/builders/nested_attributes/many.rb +32 -0
  7. data/lib/mongoid/core_ext/relations/embedded/many.rb +53 -0
  8. data/lib/mongoid/core_ext/validatable/uniqueness.rb +41 -0
  9. data/lib/mongoid/paranoia.rb +27 -18
  10. data/lib/mongoid/paranoia/version.rb +1 -1
  11. data/mongoid-paranoia.gemspec +2 -2
  12. data/spec/app/models/account.rb +0 -4
  13. data/spec/app/models/acolyte.rb +1 -1
  14. data/spec/app/models/address.rb +2 -2
  15. data/spec/app/models/appointment.rb +1 -1
  16. data/spec/app/models/article.rb +0 -3
  17. data/spec/app/models/building.rb +0 -2
  18. data/spec/app/models/building_address.rb +0 -2
  19. data/spec/app/models/contractor.rb +0 -2
  20. data/spec/app/models/dog.rb +1 -1
  21. data/spec/app/models/drug.rb +0 -2
  22. data/spec/app/models/event.rb +1 -1
  23. data/spec/app/models/game.rb +0 -2
  24. data/spec/app/models/house.rb +1 -2
  25. data/spec/app/models/item.rb +0 -4
  26. data/spec/app/models/name.rb +0 -2
  27. data/spec/app/models/paranoid_post.rb +3 -1
  28. data/spec/app/models/person.rb +3 -5
  29. data/spec/app/models/player.rb +2 -2
  30. data/spec/app/models/post.rb +2 -2
  31. data/spec/app/models/preference.rb +1 -1
  32. data/spec/app/models/quiz.rb +0 -3
  33. data/spec/app/models/registry.rb +1 -1
  34. data/spec/app/models/symptom.rb +1 -1
  35. data/spec/app/models/tree.rb +1 -1
  36. data/spec/app/models/video.rb +1 -5
  37. data/spec/app/models/wiki_page.rb +0 -2
  38. data/spec/config/mongoid.yml +0 -5
  39. data/spec/mongoid/attributes/nested_spec.rb +175 -0
  40. data/spec/mongoid/criteria/scopable_spec.rb +55 -0
  41. data/spec/mongoid/paranoia_spec.rb +3 -7
  42. data/spec/mongoid/scoping_spec.rb +55 -0
  43. data/spec/mongoid/validatable/uniqueness_spec.rb +62 -0
  44. data/spec/spec_helper.rb +2 -3
  45. metadata +33 -31
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8cc35c39d324745e9ac2fd3625d74cc8ee8f1238
4
+ data.tar.gz: 53e4e5d0f8446ae913890b7d17480b52af0e1e61
5
+ SHA512:
6
+ metadata.gz: 44901d318bd60903538cc48e7e843cdb4f952eeb510df20ea352a6e259a4eebbb49ff859a9d34509a064e59f3afd8b1405ffb74b725c352f0f0cc072a349a201
7
+ data.tar.gz: 905096d61a53be6e81448a77a3f5144ece4ca7af67671edd5c39b90179e47d2ab602ed72af0f3666b7d92551593f09474fd365e50fe9820ec62029170f6f5d27
data/.travis.yml CHANGED
@@ -3,6 +3,7 @@ language: ruby
3
3
  rvm:
4
4
  - 1.9.3
5
5
  - 2.0.0
6
+ - 2.1.0
6
7
  - ruby-head
7
8
 
8
9
  gemfile:
data/Gemfile CHANGED
@@ -4,3 +4,5 @@ gemspec
4
4
 
5
5
  gem 'rspec'
6
6
  gem 'rake'
7
+
8
+ gem 'mongoid-versioning', '1.0.0.beta1'
data/Rakefile CHANGED
@@ -1,7 +1,5 @@
1
- require 'rake/testtask'
1
+ require 'rspec/core/rake_task'
2
2
 
3
- Rake::TestTask.new do |t|
4
- t.test_files = FileList['spec/**/*_spec.rb']
5
- end
3
+ RSpec::Core::RakeTask.new(:spec)
6
4
 
7
- task default: :test
5
+ task default: :spec
@@ -1,7 +1,8 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gemspec
4
+
3
5
  gem 'mongoid', github: 'mongoid/mongoid'
4
- gem 'activesupport', '4.0.0.rc1'
5
6
 
6
7
  gem 'rspec'
7
8
  gem 'rake'
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Relations
4
+ module Builders
5
+ module NestedAttributes
6
+ class Many < NestedBuilder
7
+
8
+ # Destroy the child document, needs to do some checking for embedded
9
+ # relations and delay the destroy in case parent validation fails.
10
+ #
11
+ # @api private
12
+ #
13
+ # @example Destroy the child.
14
+ # builder.destroy(parent, relation, doc)
15
+ #
16
+ # @param [ Document ] parent The parent document.
17
+ # @param [ Proxy ] relation The relation proxy.
18
+ # @param [ Document ] doc The doc to destroy.
19
+ #
20
+ # @since 3.0.10
21
+ def destroy(parent, relation, doc)
22
+ if doc.respond_to?(:paranoid?)
23
+ destroy_document(relation, doc)
24
+ else
25
+ super
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Relations
4
+ module Embedded
5
+ class Many < Relations::Many
6
+
7
+ # Delete the supplied document from the target. This method is proxied
8
+ # in order to reindex the array after the operation occurs.
9
+ #
10
+ # @example Delete the document from the relation.
11
+ # person.addresses.delete(address)
12
+ #
13
+ # @param [ Document ] document The document to be deleted.
14
+ #
15
+ # @return [ Document, nil ] The deleted document or nil if nothing deleted.
16
+ #
17
+ # @since 2.0.0.rc.1
18
+ def delete(document)
19
+ execute_callback :before_remove, document
20
+ doc = target.delete_one(document)
21
+ if doc && !_binding?
22
+ _unscoped.delete_one(doc) unless doc.respond_to?(:paranoid?)
23
+ if _assigning?
24
+ if doc.respond_to?(:paranoid?)
25
+ doc.destroy(suppress: true)
26
+ else
27
+ base.add_atomic_pull(doc)
28
+ end
29
+ else
30
+ doc.delete(suppress: true)
31
+ unbind_one(doc)
32
+ end
33
+ end
34
+ reindex
35
+ execute_callback :after_remove, document
36
+ doc
37
+ end
38
+
39
+ # For use only with Mongoid::Paranoia - will be removed in 4.0.
40
+ #
41
+ # @example Get the deleted documents from the relation.
42
+ # person.paranoid_phones.deleted
43
+ #
44
+ # @return [ Criteria ] The deleted documents.
45
+ #
46
+ # @since 3.0.10
47
+ def deleted
48
+ unscoped.deleted
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Validatable
4
+
5
+ # Validates whether or not a field is unique against the documents in the
6
+ # database.
7
+ #
8
+ # @example Define the uniqueness validator.
9
+ #
10
+ # class Person
11
+ # include Mongoid::Document
12
+ # field :title
13
+ #
14
+ # validates_uniqueness_of :title
15
+ # end
16
+ class UniquenessValidator < ActiveModel::EachValidator
17
+
18
+ # Scope the criteria to the scope options provided.
19
+ #
20
+ # @api private
21
+ #
22
+ # @example Scope the criteria.
23
+ # validator.scope(criteria, document)
24
+ #
25
+ # @param [ Criteria ] criteria The criteria to scope.
26
+ # @param [ Document ] document The document being validated.
27
+ #
28
+ # @return [ Criteria ] The scoped criteria.
29
+ #
30
+ # @since 2.3.0
31
+ def scope(criteria, document, attribute)
32
+ Array.wrap(options[:scope]).each do |item|
33
+ name = document.database_field_name(item)
34
+ criteria = criteria.where(item => document.attributes[name])
35
+ end
36
+ criteria = criteria.where(deleted_at: nil) if document.respond_to?(:paranoid?)
37
+ criteria
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,3 +1,7 @@
1
+ require 'mongoid/core_ext/builders/nested_attributes/many'
2
+ require 'mongoid/core_ext/relations/embedded/many'
3
+ require 'mongoid/core_ext/validatable/uniqueness'
4
+
1
5
  # encoding: utf-8
2
6
  module Mongoid
3
7
 
@@ -11,14 +15,16 @@ module Mongoid
11
15
  # include Mongoid::Paranoia
12
16
  # end
13
17
  module Paranoia
18
+ include Mongoid::Persistable::Deletable
14
19
  extend ActiveSupport::Concern
15
20
 
16
21
  included do
17
22
  field :deleted_at, type: Time
23
+ class_attribute :paranoid
18
24
  self.paranoid = true
19
25
 
20
- default_scope where(deleted_at: nil)
21
- scope :deleted, ne(deleted_at: nil)
26
+ default_scope ->{ where(deleted_at: nil) }
27
+ scope :deleted, ->{ ne(deleted_at: nil) }
22
28
  end
23
29
 
24
30
  # Delete the paranoid +Document+ from the database completely. This will
@@ -34,18 +40,6 @@ module Mongoid
34
40
  run_callbacks(:destroy) { delete! }
35
41
  end
36
42
 
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
43
  # Delete the +Document+, will set the deleted_at timestamp and not actually
50
44
  # delete it.
51
45
  #
@@ -57,17 +51,28 @@ module Mongoid
57
51
  # @return [ true ] True.
58
52
  #
59
53
  # @since 1.0.0
60
- def remove(options = {})
54
+ def remove_with_paranoia(options = {})
61
55
  cascade!
62
56
  time = self.deleted_at = Time.now
63
57
  paranoid_collection.find(atomic_selector).
64
58
  update({ "$set" => { paranoid_field => time }})
65
59
  @destroyed = true
66
- IdentityMap.remove(self)
67
- clear_timeless_option
68
60
  true
69
61
  end
70
- alias :delete :remove
62
+ alias_method_chain :remove, :paranoia
63
+ alias :delete :remove_with_paranoia
64
+
65
+ # Delete the paranoid +Document+ from the database completely.
66
+ #
67
+ # @example Hard delete the document.
68
+ # document.delete!
69
+ #
70
+ # @return [ true, false ] If the operation succeeded.
71
+ #
72
+ # @since 1.0.0
73
+ def delete!
74
+ remove_without_paranoia
75
+ end
71
76
 
72
77
  # Determines if this document is destroyed.
73
78
  #
@@ -82,6 +87,10 @@ module Mongoid
82
87
  end
83
88
  alias :deleted? :destroyed?
84
89
 
90
+ def persisted?
91
+ !new_record? && !(@destroyed ||= false)
92
+ end
93
+
85
94
  # Restores a previously soft-deleted document. Handles this by removing the
86
95
  # deleted_at flag.
87
96
  #
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module Paranoia
3
- VERSION = '0.3.0'
3
+ VERSION = '1.0.0.beta1'
4
4
  end
5
5
  end
@@ -13,6 +13,6 @@ Gem::Specification.new do |gem|
13
13
  gem.files = `git ls-files`.split("\n")
14
14
  gem.require_path = 'lib'
15
15
 
16
- gem.add_dependency 'activesupport', '>= 3.0'
17
- gem.add_dependency 'mongoid', '>= 3.1.4'
16
+ gem.add_dependency 'activesupport'
17
+ gem.add_dependency 'mongoid', '4.0.0.beta1'
18
18
  end
@@ -18,10 +18,6 @@ class Account
18
18
  has_and_belongs_to_many :agents
19
19
  has_one :comment, validate: false
20
20
 
21
- attr_accessible :nickname, as: [ :default, :admin ]
22
- attr_accessible :name, as: [ :default, :admin ]
23
- attr_accessible :balance, as: :default
24
-
25
21
  validates_presence_of :name
26
22
  validates_presence_of :nickname, on: :upsert
27
23
  validates_length_of :name, maximum: 10, on: :create
@@ -6,7 +6,7 @@ class Acolyte
6
6
  embeds_many :versions, as: :memorable
7
7
  belongs_to :church
8
8
 
9
- default_scope asc(:name)
9
+ default_scope ->{ asc(:name) }
10
10
  scope :active, ->{ where(status: "active") }
11
11
  scope :named, ->{ where(:name.exists => true) }
12
12
 
@@ -38,8 +38,8 @@ class Address
38
38
  belongs_to :account
39
39
  belongs_to :band
40
40
 
41
- scope :without_postcode, where(postcode: nil)
42
- scope :rodeo, where(street: "Rodeo Dr") do
41
+ scope :without_postcode, ->{ where(postcode: nil) }
42
+ scope :rodeo, ->{ where(street: "Rodeo Dr") } do
43
43
  def mansion?
44
44
  all? { |address| address.street == "Rodeo Dr" }
45
45
  end
@@ -3,5 +3,5 @@ class Appointment
3
3
  field :active, type: Boolean, default: true
4
4
  field :timed, type: Boolean, default: true
5
5
  embedded_in :person
6
- default_scope where(active: true)
6
+ default_scope ->{ where(active: true) }
7
7
  end
@@ -5,9 +5,6 @@ class Article
5
5
  field :is_rss, type: Boolean, default: false
6
6
  field :user_login, type: String
7
7
 
8
- attr_accessible :title, as: [:default, :parser]
9
- attr_accessible :is_rss, as: :parser
10
- attr_accessible :user_login
11
8
  has_and_belongs_to_many :tags, validate: false
12
9
  has_and_belongs_to_many :preferences, inverse_of: nil, validate: false
13
10
  end
@@ -1,7 +1,5 @@
1
1
  class Building
2
2
  include Mongoid::Document
3
- attr_accessible
4
- attr_accessible :building_address, :contractors, as: :admin
5
3
  embeds_one :building_address
6
4
  embeds_many :contractors
7
5
  end
@@ -1,7 +1,5 @@
1
1
  class BuildingAddress
2
2
  include Mongoid::Document
3
- attr_accessible
4
- attr_accessible :city, as: :admin
5
3
  embedded_in :building
6
4
  field :city, type: String
7
5
  end
@@ -1,7 +1,5 @@
1
1
  class Contractor
2
2
  include Mongoid::Document
3
- attr_accessible
4
- attr_accessible :name, as: :admin
5
3
  embedded_in :building
6
4
  field :name, type: String
7
5
  end
@@ -2,5 +2,5 @@ class Dog
2
2
  include Mongoid::Document
3
3
  field :name, type: String
4
4
  has_and_belongs_to_many :breeds
5
- default_scope asc(:name)
5
+ default_scope ->{ asc(:name) }
6
6
  end
@@ -3,6 +3,4 @@ class Drug
3
3
  field :name, type: String
4
4
  field :generic, type: Boolean
5
5
  belongs_to :person, counter_cache: true
6
- attr_accessible :name, as: [ :default, :admin ]
7
- attr_accessible :person_id
8
6
  end
@@ -17,6 +17,6 @@ class Event
17
17
  end
18
18
  end
19
19
 
20
- scope :best, where(:kind.in => [ "party", "concert" ])
20
+ scope :best, ->{ where(:kind.in => [ "party", "concert" ]) }
21
21
  scope :by_kind, ->(kind){ where(:kind.in => [kind]) }
22
22
  end
@@ -13,8 +13,6 @@ class Game
13
13
 
14
14
  validates_format_of :name, without: /\$\$\$/
15
15
 
16
- attr_protected :_id
17
-
18
16
  set_callback(:initialize, :after) do |document|
19
17
  write_attribute("name", "Testing") unless name
20
18
  end
@@ -2,7 +2,6 @@ class House
2
2
  include Mongoid::Document
3
3
  field :name, type: String
4
4
  field :model, type: String
5
- attr_accessible :name, as: [ :default, :admin ]
6
5
 
7
- default_scope asc(:name)
6
+ default_scope ->{ asc(:name) }
8
7
  end
@@ -3,10 +3,6 @@ class Item
3
3
  field :title, type: String
4
4
  field :is_rss, type: Boolean, default: false
5
5
  field :user_login, type: String
6
-
7
- attr_protected :title, as: [:default, :parser]
8
- attr_protected :is_rss, as: :parser
9
- attr_protected :user_login
10
6
  end
11
7
 
12
8
  require "app/models/sub_item"
@@ -15,8 +15,6 @@ class Name
15
15
 
16
16
  accepts_nested_attributes_for :language
17
17
 
18
- attr_protected :_id, :id
19
-
20
18
  def set_parent=(set = false)
21
19
  self.parent_title = namable.title if set
22
20
  end
@@ -1,3 +1,5 @@
1
+ require 'mongoid/versioning'
2
+
1
3
  class ParanoidPost
2
4
  include Mongoid::Document
3
5
  include Mongoid::Versioning
@@ -15,7 +17,7 @@ class ParanoidPost
15
17
  has_many :authors, dependent: :delete
16
18
  has_many :titles, dependent: :restrict
17
19
 
18
- scope :recent, where(created_at: { "$lt" => Time.now, "$gt" => 30.days.ago })
20
+ scope :recent, ->{ where(created_at: { "$lt" => Time.now, "$gt" => 30.days.ago }) }
19
21
 
20
22
  before_destroy :before_destroy_stub
21
23
  after_destroy :after_destroy_stub
@@ -23,7 +23,7 @@ class Person
23
23
  field :owner_id, type: Integer
24
24
  field :security_code
25
25
  field :reading, type: Object
26
- field :bson_id, type: Moped::BSON::ObjectId
26
+ field :bson_id, type: BSON::ObjectId
27
27
  field :pattern, type: Regexp
28
28
  field :override_me, type: Integer
29
29
  field :t, as: :test, type: String
@@ -41,8 +41,6 @@ class Person
41
41
 
42
42
  attr_reader :rescored
43
43
 
44
- attr_protected :security_code, :owner_id, :appointments
45
-
46
44
  embeds_many :favorites, order: :title.desc, inverse_of: :perp, validate: false
47
45
  embeds_many :videos, order: [[ :title, :asc ]], validate: false
48
46
  embeds_many :phone_numbers, class_name: "Phone", validate: false
@@ -123,8 +121,8 @@ class Person
123
121
  accepts_nested_attributes_for :quiz
124
122
  accepts_nested_attributes_for :services, allow_destroy: true
125
123
 
126
- scope :minor, where(:age.lt => 18)
127
- scope :without_ssn, without(:ssn)
124
+ scope :minor, ->{ where(:age.lt => 18) }
125
+ scope :without_ssn, ->{ without(:ssn) }
128
126
  scope :search, ->(query){ any_of({ title: query }) }
129
127
 
130
128
  def score_with_rescoring=(score)
@@ -6,13 +6,13 @@ class Player
6
6
  field :impressions, type: Integer, default: 0
7
7
  field :status
8
8
 
9
- scope :active, where(active: true) do
9
+ scope :active, ->{ where(active: true) } do
10
10
  def extension
11
11
  "extension"
12
12
  end
13
13
  end
14
14
 
15
- scope :inactive, where(active: false)
15
+ scope :inactive, ->{ where(active: false) }
16
16
  scope :frags_over, ->(count) { where(:frags.gt => count) }
17
17
  scope :deaths_under, ->(count) { where(:deaths.lt => count) }
18
18
  scope :deaths_over, ->(count) { where(:deaths.gt => count) }
@@ -13,8 +13,8 @@ class Post
13
13
  has_and_belongs_to_many :tags, before_add: :before_add_tag, after_add: :after_add_tag, before_remove: :before_remove_tag, after_remove: :after_remove_tag
14
14
  has_many :videos, validate: false
15
15
 
16
- scope :recent, where(created_at: { "$lt" => Time.now, "$gt" => 30.days.ago })
17
- scope :posting, where(:content.in => [ "Posting" ])
16
+ scope :recent, ->{ where(created_at: { "$lt" => Time.now, "$gt" => 30.days.ago }) }
17
+ scope :posting, ->{ where(:content.in => [ "Posting" ]) }
18
18
 
19
19
  validates_format_of :title, without: /\$\$\$/
20
20
 
@@ -5,5 +5,5 @@ class Preference
5
5
  field :ranking, type: Integer
6
6
  has_and_belongs_to_many :people, validate: false
7
7
  validates_length_of :name, minimum: 2, allow_nil: true
8
- scope :posting, where(:value.in => [ "Posting" ])
8
+ scope :posting, ->{ where(:value.in => [ "Posting" ]) }
9
9
  end
@@ -4,7 +4,4 @@ class Quiz
4
4
  field :name, type: String
5
5
  field :topic, type: String
6
6
  embeds_many :pages
7
-
8
- attr_accessible :topic, as: [ :default, :admin ]
9
- attr_accessible :name, as: :default
10
7
  end
@@ -1,4 +1,4 @@
1
1
  class Registry
2
2
  include Mongoid::Document
3
- field :data, type: Moped::BSON::Binary
3
+ field :data, type: BSON::Binary
4
4
  end
@@ -2,5 +2,5 @@ class Symptom
2
2
  include Mongoid::Document
3
3
  field :name, type: String
4
4
  embedded_in :person
5
- default_scope asc(:name)
5
+ default_scope ->{ asc(:name) }
6
6
  end
@@ -5,5 +5,5 @@ class Tree
5
5
  field :evergreen, type: Boolean
6
6
 
7
7
  scope :verdant, where(evergreen: true)
8
- default_scope asc(:name)
8
+ default_scope ->{ asc(:name) }
9
9
  end
@@ -9,9 +9,5 @@ class Video
9
9
  belongs_to :post
10
10
  belongs_to :game
11
11
 
12
- default_scope asc(:title)
13
-
14
- attr_accessible :title, as: [ :default, :admin ]
15
- attr_accessible :year, as: [ :default ]
16
- attr_accessible :person_attributes, as: [ :default ]
12
+ default_scope ->{ asc(:title) }
17
13
  end
@@ -9,8 +9,6 @@ class WikiPage
9
9
  field :description, type: String, localize: true
10
10
  max_versions 5
11
11
 
12
- attr_protected :author
13
-
14
12
  has_many :comments, dependent: :destroy, validate: false
15
13
  has_many :child_pages, class_name: "WikiPage", dependent: :delete, inverse_of: :parent_pages
16
14
  belongs_to :parent_pages, class_name: "WikiPage", inverse_of: :child_pages
@@ -4,8 +4,6 @@ test:
4
4
  database: mongoid_test
5
5
  hosts:
6
6
  - <%=ENV["MONGOID_SPEC_HOST"]%>:<%=ENV["MONGOID_SPEC_PORT"]%>
7
- options:
8
- consistency: :strong
9
7
  mongohq_single:
10
8
  database: <%=ENV["MONGOHQ_SINGLE_NAME"]%>
11
9
  username: <%=ENV["MONGOHQ_SINGLE_USER"]%>
@@ -14,7 +12,6 @@ test:
14
12
  - <%=ENV["MONGOHQ_SINGLE_URL"]%>
15
13
  options:
16
14
  safe: true
17
- consistency: :strong
18
15
  mongohq_repl:
19
16
  database: <%=ENV["MONGOHQ_REPL_NAME"]%>
20
17
  username: <%=ENV["MONGOHQ_REPL_USER"]%>
@@ -23,13 +20,11 @@ test:
23
20
  - <%=ENV["MONGOHQ_REPL_1_URL"]%>
24
21
  - <%=ENV["MONGOHQ_REPL_2_URL"]%>
25
22
  options:
26
- consistency: :strong
27
23
  safe: true
28
24
  mongohq_repl_uri:
29
25
  uri: <%= ENV["MONGOHQ_REPL_URI"]%>
30
26
  options:
31
27
  allow_dynamic_fields: true
32
- identity_map_enabled: false
33
28
  include_root_in_json: false
34
29
  include_type_for_serialization: false
35
30
  preload_models: false
@@ -0,0 +1,175 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Attributes::Nested do
4
+
5
+ describe "##{name}_attributes=" do
6
+
7
+ context "when the parent document is new" do
8
+
9
+ context "when the relation is an embeds many" do
10
+
11
+ let(:person) do
12
+ Person.new
13
+ end
14
+
15
+ let(:address_one) do
16
+ Address.new(street: "Unter den Linden")
17
+ end
18
+
19
+ let(:address_two) do
20
+ Address.new(street: "Kurfeurstendamm")
21
+ end
22
+
23
+ let(:phone_one) do
24
+ ParanoidPhone.new(number: "1")
25
+ end
26
+
27
+ let(:phone_two) do
28
+ ParanoidPhone.new(number: "2")
29
+ end
30
+
31
+ context "when ids are passed" do
32
+
33
+ before do
34
+ person.addresses << [ address_one, address_two ]
35
+ end
36
+
37
+ context "when destroy attributes are passed" do
38
+
39
+ context "when the ids match" do
40
+
41
+ context "when allow_destroy is true" do
42
+
43
+ context "when the child has defaults" do
44
+
45
+ before(:all) do
46
+ Person.accepts_nested_attributes_for :appointments, allow_destroy: true
47
+ end
48
+
49
+ after(:all) do
50
+ Person.send(:undef_method, :appointments_attributes=)
51
+ end
52
+
53
+ context "when the parent is persisted" do
54
+
55
+ let!(:persisted) do
56
+ Person.create(age: 42)
57
+ end
58
+
59
+ context "when the child returns false in a before callback" do
60
+
61
+ context "when the child is paranoid" do
62
+
63
+ before(:all) do
64
+ Person.accepts_nested_attributes_for :paranoid_phones, allow_destroy: true
65
+ end
66
+
67
+ after(:all) do
68
+ Person.send(:undef_method, :paranoid_phones=)
69
+ Person.accepts_nested_attributes_for :paranoid_phones
70
+ end
71
+
72
+ let!(:phone) do
73
+ persisted.paranoid_phones.create
74
+ end
75
+
76
+ before do
77
+ persisted.paranoid_phones_attributes =
78
+ { "foo" => { "id" => phone.id, "number" => 42, "_destroy" => true }}
79
+ end
80
+
81
+ it "does not destroy the child" do
82
+ persisted.reload.paranoid_phones.should_not be_empty
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ context "when the child is paranoid" do
90
+
91
+ before(:all) do
92
+ Person.send(:undef_method, :paranoid_phones_attributes=)
93
+ Person.accepts_nested_attributes_for :paranoid_phones,
94
+ allow_destroy: true
95
+ end
96
+
97
+ after(:all) do
98
+ Person.send(:undef_method, :paranoid_phones_attributes=)
99
+ Person.accepts_nested_attributes_for :paranoid_phones
100
+ end
101
+
102
+ [ 1, "1", true, "true" ].each do |truth|
103
+
104
+ context "when passed a #{truth} with destroy" do
105
+
106
+ context "when the parent is persisted" do
107
+
108
+ let!(:persisted) do
109
+ Person.create do |p|
110
+ p.paranoid_phones << [ phone_one, phone_two ]
111
+ end
112
+ end
113
+
114
+ context "when setting, pulling, and pushing in one op" do
115
+
116
+ before do
117
+ persisted.paranoid_phones_attributes =
118
+ {
119
+ "bar" => { "id" => phone_one.id, "_destroy" => truth },
120
+ "foo" => { "id" => phone_two.id, "number" => "3" },
121
+ "baz" => { "number" => "4" }
122
+ }
123
+ end
124
+
125
+ it "removes the first document from the relation" do
126
+ persisted.paranoid_phones.size.should eq(2)
127
+ end
128
+
129
+ it "does not delete the unmarked document" do
130
+ persisted.paranoid_phones.first.number.should eq("3")
131
+ end
132
+
133
+ it "adds the new document to the relation" do
134
+ persisted.paranoid_phones.last.number.should eq("4")
135
+ end
136
+
137
+ it "has the proper persisted count" do
138
+ persisted.paranoid_phones.count.should eq(1)
139
+ end
140
+
141
+ it "soft deletes the removed document" do
142
+ phone_one.should be_destroyed
143
+ end
144
+
145
+ context "when saving the parent" do
146
+
147
+ before do
148
+ persisted.with(safe: true).save
149
+ end
150
+
151
+ it "deletes the marked document from the relation" do
152
+ persisted.reload.paranoid_phones.count.should eq(2)
153
+ end
154
+
155
+ it "does not delete the unmarked document" do
156
+ persisted.reload.paranoid_phones.first.number.should eq("3")
157
+ end
158
+
159
+ it "persists the new document to the relation" do
160
+ persisted.reload.paranoid_phones.last.number.should eq("4")
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,55 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Criteria::Scopable do
4
+
5
+ context "when the document is paranoid" do
6
+
7
+ context "when calling a class method" do
8
+
9
+ let(:criteria) do
10
+ Fish.fresh
11
+ end
12
+
13
+ it "includes the deleted_at criteria in the selector" do
14
+ criteria.selector.should eq({
15
+ "deleted_at" => nil, "fresh" => true
16
+ })
17
+ end
18
+ end
19
+
20
+ context "when chaining a class method to unscoped" do
21
+
22
+ let(:criteria) do
23
+ Fish.unscoped.fresh
24
+ end
25
+
26
+ it "does not include the deleted_at in the selector" do
27
+ criteria.selector.should eq({ "fresh" => true })
28
+ end
29
+ end
30
+
31
+ context "when chaining a class method to deleted" do
32
+
33
+ let(:criteria) do
34
+ Fish.deleted.fresh
35
+ end
36
+
37
+ it "includes the deleted_at $ne criteria in the selector" do
38
+ criteria.selector.should eq({
39
+ "deleted_at" => { "$ne" => nil }, "fresh" => true
40
+ })
41
+ end
42
+ end
43
+
44
+ context "when chaining a where to unscoped" do
45
+
46
+ let(:criteria) do
47
+ Fish.unscoped.where(fresh: true)
48
+ end
49
+
50
+ it "includes no default scoping information in the selector" do
51
+ criteria.selector.should eq({ "fresh" => true })
52
+ end
53
+ end
54
+ end
55
+ end
@@ -46,7 +46,7 @@ describe Mongoid::Paranoia do
46
46
  end
47
47
 
48
48
  it "returns the deleted documents" do
49
- person.paranoid_phones.deleted.should eq([ phone ])
49
+ person.paranoid_phones.deleted.to_a.should eq([ phone ])
50
50
  end
51
51
 
52
52
  it "returns the correct count" do
@@ -480,11 +480,7 @@ describe Mongoid::Paranoia do
480
480
  end
481
481
 
482
482
  it "clears out the persistence options" do
483
- Mongoid::Threaded.persistence_options(ParanoidPost).should be_nil
484
- end
485
-
486
- it "clears out the identity map" do
487
- Mongoid::IdentityMap.should be_empty
483
+ ParanoidPost.persistence_options.should be_nil
488
484
  end
489
485
  end
490
486
 
@@ -657,7 +653,7 @@ describe Mongoid::Paranoia do
657
653
  end
658
654
 
659
655
  before do
660
- post.set(:deleted_at, time)
656
+ post.set(deleted_at: time)
661
657
  end
662
658
 
663
659
  it "persists the change" do
@@ -0,0 +1,55 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Criteria::Scopable do
4
+
5
+ context "when the document is paranoid" do
6
+
7
+ context "when calling a class method" do
8
+
9
+ let(:criteria) do
10
+ Fish.fresh
11
+ end
12
+
13
+ it "includes the deleted_at criteria in the selector" do
14
+ criteria.selector.should eq({
15
+ "deleted_at" => nil, "fresh" => true
16
+ })
17
+ end
18
+ end
19
+
20
+ context "when chaining a class method to unscoped" do
21
+
22
+ let(:criteria) do
23
+ Fish.unscoped.fresh
24
+ end
25
+
26
+ it "does not include the deleted_at in the selector" do
27
+ criteria.selector.should eq({ "fresh" => true })
28
+ end
29
+ end
30
+
31
+ context "when chaining a class method to deleted" do
32
+
33
+ let(:criteria) do
34
+ Fish.deleted.fresh
35
+ end
36
+
37
+ it "includes the deleted_at $ne criteria in the selector" do
38
+ criteria.selector.should eq({
39
+ "deleted_at" => { "$ne" => nil }, "fresh" => true
40
+ })
41
+ end
42
+ end
43
+
44
+ context "when chaining a where to unscoped" do
45
+
46
+ let(:criteria) do
47
+ Fish.unscoped.where(fresh: true)
48
+ end
49
+
50
+ it "includes no default scoping information in the selector" do
51
+ criteria.selector.should eq({ "fresh" => true })
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,62 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Validatable::UniquenessValidator do
4
+
5
+ describe "#valid?" do
6
+
7
+ context "when the document is a root document" do
8
+
9
+ context "when the document is paranoid" do
10
+
11
+ before do
12
+ ParanoidPost.validates_uniqueness_of :title
13
+ end
14
+
15
+ after do
16
+ ParanoidPost.reset_callbacks(:validate)
17
+ end
18
+
19
+ let!(:post) do
20
+ ParanoidPost.create(title: "testing")
21
+ end
22
+
23
+ context "when the field is unique" do
24
+
25
+ let(:new_post) do
26
+ ParanoidPost.new(title: "test")
27
+ end
28
+
29
+ it "returns true" do
30
+ new_post.should be_valid
31
+ end
32
+ end
33
+
34
+ context "when the field is unique for non soft deleted docs" do
35
+
36
+ before do
37
+ post.delete
38
+ end
39
+
40
+ let(:new_post) do
41
+ ParanoidPost.new(title: "testing")
42
+ end
43
+
44
+ it "returns true" do
45
+ new_post.should be_valid
46
+ end
47
+ end
48
+
49
+ context "when the field is not unique" do
50
+
51
+ let(:new_post) do
52
+ ParanoidPost.new(title: "testing")
53
+ end
54
+
55
+ it "returns false" do
56
+ new_post.should_not be_valid
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
data/spec/spec_helper.rb CHANGED
@@ -36,7 +36,7 @@ end
36
36
 
37
37
  # Set the database that the spec suite connects to.
38
38
  Mongoid.configure do |config|
39
- config.connect_to(database_id, consistency: :strong)
39
+ config.connect_to(database_id)
40
40
  end
41
41
 
42
42
  # Autoload every model for the test suite that sits in spec/app/models.
@@ -57,10 +57,9 @@ end
57
57
 
58
58
  RSpec.configure do |config|
59
59
 
60
- # Drop all collections and clear the identity map before each spec.
60
+ # Drop all collections before each spec.
61
61
  config.before(:each) do
62
62
  Mongoid.purge!
63
- Mongoid::IdentityMap.clear
64
63
  end
65
64
 
66
65
  # On travis we are creating many different databases on each test run. We
metadata CHANGED
@@ -1,48 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid-paranoia
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.3.0
4
+ version: 1.0.0.beta1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Mario Uher
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-05-28 00:00:00.000000000 Z
11
+ date: 2014-04-09 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
- prerelease: false
16
- version_requirements: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - ! '>='
19
- - !ruby/object:Gem::Version
20
- version: '3.0'
21
- none: false
22
- type: :runtime
23
14
  name: activesupport
24
15
  requirement: !ruby/object:Gem::Requirement
25
16
  requirements:
26
- - - ! '>='
17
+ - - ">="
27
18
  - !ruby/object:Gem::Version
28
- version: '3.0'
29
- none: false
30
- - !ruby/object:Gem::Dependency
19
+ version: '0'
20
+ type: :runtime
31
21
  prerelease: false
32
22
  version_requirements: !ruby/object:Gem::Requirement
33
23
  requirements:
34
- - - ! '>='
24
+ - - ">="
35
25
  - !ruby/object:Gem::Version
36
- version: 3.1.4
37
- none: false
38
- type: :runtime
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
39
28
  name: mongoid
40
29
  requirement: !ruby/object:Gem::Requirement
41
30
  requirements:
42
- - - ! '>='
31
+ - - '='
43
32
  - !ruby/object:Gem::Version
44
- version: 3.1.4
45
- none: false
33
+ version: 4.0.0.beta1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 4.0.0.beta1
46
41
  description: There may be times when you don't want documents to actually get deleted
47
42
  from the database, but "flagged" as deleted.
48
43
  email: uher.mario@gmail.com
@@ -50,13 +45,16 @@ executables: []
50
45
  extensions: []
51
46
  extra_rdoc_files: []
52
47
  files:
53
- - .gitignore
54
- - .travis.yml
48
+ - ".gitignore"
49
+ - ".travis.yml"
55
50
  - CHANGELOG.md
56
51
  - Gemfile
57
52
  - README.md
58
53
  - Rakefile
59
54
  - gemfiles/mongoid_master.gemfile
55
+ - lib/mongoid/core_ext/builders/nested_attributes/many.rb
56
+ - lib/mongoid/core_ext/relations/embedded/many.rb
57
+ - lib/mongoid/core_ext/validatable/uniqueness.rb
60
58
  - lib/mongoid/paranoia.rb
61
59
  - lib/mongoid/paranoia/version.rb
62
60
  - mongoid-paranoia.gemspec
@@ -244,30 +242,34 @@ files:
244
242
  - spec/app/models/word_origin.rb
245
243
  - spec/app/models/writer.rb
246
244
  - spec/config/mongoid.yml
245
+ - spec/mongoid/attributes/nested_spec.rb
246
+ - spec/mongoid/criteria/scopable_spec.rb
247
247
  - spec/mongoid/paranoia_spec.rb
248
+ - spec/mongoid/scoping_spec.rb
249
+ - spec/mongoid/validatable/uniqueness_spec.rb
248
250
  - spec/spec_helper.rb
249
251
  homepage: https://github.com/haihappen/mongoid-paranoia
250
252
  licenses: []
253
+ metadata: {}
251
254
  post_install_message:
252
255
  rdoc_options: []
253
256
  require_paths:
254
257
  - lib
255
258
  required_ruby_version: !ruby/object:Gem::Requirement
256
259
  requirements:
257
- - - ! '>='
260
+ - - ">="
258
261
  - !ruby/object:Gem::Version
259
262
  version: '0'
260
- none: false
261
263
  required_rubygems_version: !ruby/object:Gem::Requirement
262
264
  requirements:
263
- - - ! '>='
265
+ - - ">"
264
266
  - !ruby/object:Gem::Version
265
- version: '0'
266
- none: false
267
+ version: 1.3.1
267
268
  requirements: []
268
269
  rubyforge_project:
269
- rubygems_version: 1.8.25
270
+ rubygems_version: 2.2.0
270
271
  signing_key:
271
- specification_version: 3
272
+ specification_version: 4
272
273
  summary: Extraction of mongoid-paranoia into its own gem.
273
274
  test_files: []
275
+ has_rdoc: