sepastian-mongoid-paranoia-rails4 0.0.1.alpha

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --tty
2
+ --colour
3
+ --format <%= ENV["CI"] ? 'progress' : 'documentation'%>
@@ -0,0 +1,20 @@
1
+ language: ruby
2
+ bundler_args: --without development
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - jruby
7
+ jdk:
8
+ - oraclejdk7
9
+ - openjdk7
10
+ env: JRUBY_OPTS="--server -Xcompile.invokedynamic=false -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1 -J-noverify -J-Xms512m -J-Xmx1024m"
11
+ services:
12
+ - mongodb
13
+ matrix:
14
+ exclude:
15
+ - rvm: 1.9.3
16
+ jdk: oraclejdk7
17
+ env: JRUBY_OPTS="--server -Xcompile.invokedynamic=false -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1 -J-noverify -J-Xms512m -J-Xmx1024m"
18
+ - rvm: 2.0.0
19
+ jdk: oraclejdk7
20
+ env: JRUBY_OPTS="--server -Xcompile.invokedynamic=false -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1 -J-noverify -J-Xms512m -J-Xmx1024m"
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem "rake"
6
+ # gem "mongoid", github: 'mongoid', branch: "master"
7
+
8
+ group :test do
9
+ gem "rspec", "~> 2.11"
10
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Josef Šimánek
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,68 @@
1
+ # Paranoid Documents for Mongoid 4 [![Build Status](https://travis-ci.org/simi/mongoid-paranoia.png?branch=master)](https://travis-ci.org/simi/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-paranoia provides a Paranoia module to give you just that.
4
+
5
+ **Old API** from Mongoid 3.0 is extracted in [3.0.0-stable branch](https://github.com/simi/mongoid-paranoia/tree/3.0.0-stable) and **doesn't work** with **Mongoid 4** anymore.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'mongoid-paranoia', github: 'simi/mongoid-paranoia' # before first release
13
+ ```
14
+
15
+ ## Changes in 4.0
16
+ ### [Uniqueness validator is not overriding default one](https://github.com/simi/mongoid-paranoia/commit/ce69dfeeb3f625535749ac919f2f643d47f3cdf4)
17
+ This will be changed soon - https://github.com/simi/mongoid-paranoia/issues/5. Please leave a note if you don't like this behaviour, it will be merged soon.
18
+
19
+ #### Old syntax:
20
+ ```ruby
21
+ validates_uniqueness_of :title
22
+ validates :title, :uniqueness => true
23
+ ```
24
+
25
+ #### New syntax:
26
+ ```ruby
27
+ validates :title, :uniqueness_including_deleted => true
28
+ ```
29
+
30
+
31
+ ## Usage
32
+
33
+ ```ruby
34
+ class Person
35
+ include Mongoid::Document
36
+ include Mongoid::Paranoia
37
+ end
38
+
39
+ person.delete # Sets the deleted_at field to the current time, ignoring callbacks.
40
+ person.delete! # Permanently deletes the document, ignoring callbacks.
41
+ person.destroy # Sets the deleted_at field to the current time, firing callbacks.
42
+ person.destroy! # Permanently deletes the document, firing callbacks.
43
+ person.restore # Brings the "deleted" document back to life.
44
+ ```
45
+
46
+ 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.
47
+
48
+ ```ruby
49
+ Person.deleted # Returns documents that have been "flagged" as deleted.
50
+ ```
51
+
52
+ You can also access all documents (both deleted and non-deleted) at any time by using the `unscoped` class method:
53
+
54
+ ```ruby
55
+ Person.unscoped.all # Returns all documents, both deleted and non-deleted
56
+ ```
57
+
58
+ ## TODO
59
+ - get rid of [monkey_patches.rb](https://github.com/simi/mongoid-paranoia/blob/master/lib/mongoid/paranoia/monkey_patches.rb)
60
+ - [review persisted? behaviour](https://github.com/simi/mongoid-paranoia/issues/2)
61
+
62
+ ## Contributing
63
+
64
+ 1. Fork it
65
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
66
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
67
+ 4. Push to the branch (`git push origin my-new-feature`)
68
+ 5. Create new Pull Request
@@ -0,0 +1,13 @@
1
+ require "bundler"
2
+ Bundler.setup
3
+
4
+ require "rspec/core/rake_task"
5
+ require "rake"
6
+
7
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
8
+
9
+ RSpec::Core::RakeTask.new("spec") do |spec|
10
+ spec.pattern = "spec/**/*_spec.rb"
11
+ end
12
+
13
+ task :default => :spec
@@ -0,0 +1 @@
1
+ require "mongoid/paranoia"
@@ -0,0 +1,137 @@
1
+ # encoding: utf-8
2
+ require 'mongoid/paranoia/monkey_patches'
3
+ require 'mongoid/validatable/uniqueness_including_deleted_validator'
4
+ module Mongoid
5
+
6
+ # Include this module to get soft deletion of root level documents.
7
+ # This will add a deleted_at field to the +Document+, managed automatically.
8
+ # Potentially incompatible with unique indices. (if collisions with deleted items)
9
+ #
10
+ # @example Make a document paranoid.
11
+ # class Person
12
+ # include Mongoid::Document
13
+ # include Mongoid::Paranoia
14
+ # end
15
+ module Paranoia
16
+ include Mongoid::Persistable::Deletable
17
+ extend ActiveSupport::Concern
18
+
19
+ included do
20
+ field :deleted_at, type: Time
21
+ class_attribute :paranoid
22
+ self.paranoid = true
23
+
24
+ default_scope where(deleted_at: nil)
25
+ scope :deleted, ne(deleted_at: nil)
26
+ end
27
+
28
+ # Delete the paranoid +Document+ from the database completely. This will
29
+ # run the destroy callbacks.
30
+ #
31
+ # @example Hard destroy the document.
32
+ # document.destroy!
33
+ #
34
+ # @return [ true, false ] If the operation succeeded.
35
+ #
36
+ # @since 1.0.0
37
+ def destroy!
38
+ run_callbacks(:destroy) { delete! }
39
+ end
40
+
41
+ # Delete the +Document+, will set the deleted_at timestamp and not actually
42
+ # delete it.
43
+ #
44
+ # @example Soft remove the document.
45
+ # document.remove
46
+ #
47
+ # @param [ Hash ] options The database options.
48
+ #
49
+ # @return [ true ] True.
50
+ #
51
+ # @since 1.0.0
52
+ def remove_with_paranoia(options = {})
53
+ cascade!
54
+ time = self.deleted_at = Time.now
55
+ paranoid_collection.find(atomic_selector).
56
+ update({ "$set" => { paranoid_field => time }})
57
+ @destroyed = true
58
+ IdentityMap.remove(self)
59
+ true
60
+ end
61
+ alias_method_chain :remove, :paranoia
62
+ alias :delete :remove
63
+
64
+ # Delete the paranoid +Document+ from the database completely.
65
+ #
66
+ # @example Hard delete the document.
67
+ # document.delete!
68
+ #
69
+ # @return [ true, false ] If the operation succeeded.
70
+ #
71
+ # @since 1.0.0
72
+ def delete!
73
+ remove_without_paranoia
74
+ end
75
+
76
+ # Determines if this document is destroyed.
77
+ #
78
+ # @example Is the document destroyed?
79
+ # person.destroyed?
80
+ #
81
+ # @return [ true, false ] If the document is destroyed.
82
+ #
83
+ # @since 1.0.0
84
+ def destroyed?
85
+ (@destroyed ||= false) || !!deleted_at
86
+ end
87
+ alias :deleted? :destroyed?
88
+
89
+ # Restores a previously soft-deleted document. Handles this by removing the
90
+ # deleted_at flag.
91
+ #
92
+ # @example Restore the document from deleted state.
93
+ # document.restore
94
+ #
95
+ # @return [ Time ] The time the document had been deleted.
96
+ #
97
+ # @since 1.0.0
98
+ def restore
99
+ paranoid_collection.find(atomic_selector).
100
+ update({ "$unset" => { paranoid_field => true }})
101
+ attributes.delete("deleted_at")
102
+ @destroyed = false
103
+ true
104
+ end
105
+
106
+ # Returns a string representing the documents's key suitable for use in URLs.
107
+ def to_param
108
+ new_record? ? nil : to_key.join('-')
109
+ end
110
+
111
+ private
112
+
113
+ # Get the collection to be used for paranoid operations.
114
+ #
115
+ # @example Get the paranoid collection.
116
+ # document.paranoid_collection
117
+ #
118
+ # @return [ Collection ] The root collection.
119
+ #
120
+ # @since 2.3.1
121
+ def paranoid_collection
122
+ embedded? ? _root.collection : self.collection
123
+ end
124
+
125
+ # Get the field to be used for paranoid operations.
126
+ #
127
+ # @example Get the paranoid field.
128
+ # document.paranoid_field
129
+ #
130
+ # @return [ String ] The deleted at field.
131
+ #
132
+ # @since 2.3.1
133
+ def paranoid_field
134
+ embedded? ? "#{atomic_position}.deleted_at" : "deleted_at"
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,95 @@
1
+ module Mongoid
2
+ module Relations
3
+ module Builders
4
+ module NestedAttributes
5
+ class Many < NestedBuilder
6
+ # Destroy the child document, needs to do some checking for embedded
7
+ # relations and delay the destroy in case parent validation fails.
8
+ #
9
+ # @api private
10
+ #
11
+ # @example Destroy the child.
12
+ # builder.destroy(parent, relation, doc)
13
+ #
14
+ # @param [ Document ] parent The parent document.
15
+ # @param [ Proxy ] relation The relation proxy.
16
+ # @param [ Document ] doc The doc to destroy.
17
+ #
18
+ # @since 3.0.10
19
+ def destroy(parent, relation, doc)
20
+ doc.flagged_for_destroy = true
21
+ if !doc.embedded? || parent.new_record? || doc.respond_to?(:paranoid)
22
+ destroy_document(relation, doc)
23
+ else
24
+ parent.flagged_destroys.push(->{ destroy_document(relation, doc) })
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ module Mongoid
34
+ module Relations
35
+ module Embedded
36
+ # This class handles the behaviour for a document that embeds many other
37
+ # documents within in it as an array.
38
+ class Many < Relations::Many
39
+ # Delete the supplied document from the target. This method is proxied
40
+ # in order to reindex the array after the operation occurs.
41
+ #
42
+ # @example Delete the document from the relation.
43
+ # person.addresses.delete(address)
44
+ #
45
+ # @param [ Document ] document The document to be deleted.
46
+ #
47
+ # @return [ Document, nil ] The deleted document or nil if nothing deleted.
48
+ #
49
+ # @since 2.0.0.rc.1
50
+ def delete(document)
51
+ execute_callback :before_remove, document
52
+ doc = target.delete_one(document)
53
+ if doc && !_binding?
54
+ _unscoped.delete_one(doc) unless doc.respond_to?(:paranoid)
55
+ if _assigning?
56
+ if doc.respond_to?(:paranoid)
57
+ doc.destroy(suppress: true)
58
+ else
59
+ base.add_atomic_pull(doc)
60
+ end
61
+ else
62
+ doc.delete(suppress: true)
63
+ unbind_one(doc)
64
+ end
65
+ end
66
+ reindex
67
+ execute_callback :after_remove, document
68
+ doc
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ module Mongoid
76
+ module Relations
77
+ module Embedded
78
+ class Many < Relations::Many
79
+ # For use only with Mongoid::Paranoia - will be removed in 4.0.
80
+ #
81
+ # @example Get the deleted documents from the relation.
82
+ # person.paranoid_phones.deleted
83
+ #
84
+ # @return [ Criteria ] The deleted documents.
85
+ #
86
+ # @since 3.0.10
87
+ def deleted
88
+ unscoped.deleted
89
+ end
90
+ # This class handles the behaviour for a document that embeds many other
91
+ # documents within in it as an array.
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Validatable
4
+ # Validates whether or not a field is unique against the documents in the
5
+ # database including deleted documents for paranoic models.
6
+ #
7
+ # @example Define the uniqueness validator.
8
+ #
9
+ # class Person
10
+ # include Mongoid::Document
11
+ # include Mongoid::Paranoia
12
+ # field :title
13
+ #
14
+ # validates :title, :uniqueness_including_deleted => true
15
+ # end
16
+ class UniquenessIncludingDeletedValidator < Mongoid::Validatable::UniquenessValidator
17
+ # Scope the criteria to the scope options provided.
18
+ # Added Paranoia spice.
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 4.0.0
31
+ def scope(criteria, document, attribute)
32
+ criteria = super
33
+ criteria = criteria.where(deleted_at: nil) if document.respond_to?(:paranoid)
34
+ criteria
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "sepastian-mongoid-paranoia-rails4"
7
+ gem.version = "0.0.1.alpha"
8
+ gem.authors = ["Sebastian Gassner"]
9
+ gem.email = ["sebastian.gassner@gmail.com"]
10
+ gem.summary = %q{A fork of the mongoid master branch, supporting Rails 4.}
11
+ gem.description = %q{Mongoid fork with support for Rails 4, for gem development. When releasing a gem, the gem can only depend on other released gems, not on github sources or paths. Mongoid has not yet released a gem supporting Rails 4. This gem is just a packaged version of the mongoid master branch, filling the gap until a release of mongoid with support for Rails 4.}
12
+ gem.homepage = "https://github.com/sepastian/mongoid-paranoia"
13
+ gem.rubyforge_project = "sepastian-mongoid-paranoia-rails4"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency "activemodel", ['~> 4.0.0']
21
+ gem.add_dependency "sepastian-mongoid-rails4", '~> 4.0.0.alpha'
22
+ gem.add_development_dependency "rspec", '~> 2.11'
23
+ end