semanticart-is_paranoid 0.9.5 → 0.9.6
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.
- data/CHANGELOG +3 -0
- data/README.textile +12 -2
- data/VERSION.yml +2 -2
- data/is_paranoid.gemspec +2 -2
- data/lib/is_paranoid.rb +23 -0
- data/spec/is_paranoid_spec.rb +18 -1
- data/spec/models.rb +21 -2
- data/spec/schema.rb +18 -0
- metadata +2 -2
data/CHANGELOG
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
This will only document major changes. Please see the commit log for minor changes.
|
2
2
|
|
3
|
+
-2009-09-25
|
4
|
+
* fixing bug with has_many :through not respecting is_paranoid conditions (thanks, Ben Johnson)
|
5
|
+
|
3
6
|
-2009-09-18
|
4
7
|
* making is_paranoid play nice with habtm relationships
|
5
8
|
|
data/README.textile
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
h1. is_paranoid ( same as it ever was )
|
2
2
|
|
3
|
+
h3. advice and disclaimer
|
4
|
+
|
5
|
+
You should always declare is_paranoid before any associations in your model unless you have a good reason for doing otherwise. Some relationships might not behave properly if you fail to do so. If you know what you're doing (and have written tests) and want to supress the warning then you can pass :suppress_load_order_warning => true as an option.
|
6
|
+
|
7
|
+
<pre>
|
8
|
+
is_paranoid :suppress_load_order_warning => true
|
9
|
+
</pre>
|
10
|
+
|
11
|
+
You should never expect _any_ library to work or behave exactly how you want it to: test, test, test and file an issue if you have any problems. Bonus points if you include sample failing code. Extra bonus points if you send a pull request that implements a feature/fixes a bug.
|
12
|
+
|
3
13
|
h3. and you may ask yourself, well, how did I get here?
|
4
14
|
|
5
15
|
Sometimes you want to delete something in ActiveRecord, but you realize you might need it later (for an undo feature, or just as a safety net, etc.). There are a plethora of plugins that accomplish this, the most famous of which is the venerable acts_as_paranoid which is great but not really actively developed any more. What's more, acts_as_paranoid was written for an older version of ActiveRecord and, with default_scope in 2.3, it is now possible to do the same thing with significantly less complexity. Thus, *is_paranoid*.
|
@@ -91,7 +101,7 @@ And now the validates_uniqueness_of will ignore items that are destroyed.
|
|
91
101
|
|
92
102
|
h3. and you may ask yourself, where does that highway go to?
|
93
103
|
|
94
|
-
If you find any bugs, have any ideas of features you think are missing, or find things you're like to see work differently, feel free to
|
104
|
+
If you find any bugs, have any ideas of features you think are missing, or find things you're like to see work differently, feel free to file an issue or send a pull request.
|
95
105
|
|
96
106
|
Currently on the todo list:
|
97
107
|
* add options for merging additional default_scope options (i.e. order, etc.)
|
@@ -100,4 +110,4 @@ h3. Thanks
|
|
100
110
|
|
101
111
|
Thanks to Rick Olson for acts_as_paranoid which is obviously an inspiration in concept and execution, Ryan Bates for mentioning the idea of using default_scope for this on Ryan Daigle's "post introducing default_scope":defscope, and the Talking Heads for being the Talking Heads.
|
102
112
|
|
103
|
-
[defscope]http://ryandaigle.com/articles/2008/11/18/what-s-new-in-edge-rails-default-scoping
|
113
|
+
[defscope]http://ryandaigle.com/articles/2008/11/18/what-s-new-in-edge-rails-default-scoping
|
data/VERSION.yml
CHANGED
data/is_paranoid.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{is_paranoid}
|
8
|
-
s.version = "0.9.
|
8
|
+
s.version = "0.9.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jeffrey Chupp"]
|
12
|
-
s.date = %q{2009-09-
|
12
|
+
s.date = %q{2009-09-26}
|
13
13
|
s.description = %q{}
|
14
14
|
s.email = %q{jeff@semanticart.com}
|
15
15
|
s.extra_rdoc_files = [
|
data/lib/is_paranoid.rb
CHANGED
@@ -15,6 +15,10 @@ module IsParanoid
|
|
15
15
|
class_inheritable_accessor :destroyed_field, :field_destroyed, :field_not_destroyed
|
16
16
|
self.destroyed_field, self.field_destroyed, self.field_not_destroyed = opts[:field]
|
17
17
|
|
18
|
+
if self.reflect_on_all_associations.size > 0 && ! opts[:suppress_load_order_warning]
|
19
|
+
warn "is_paranoid warning in class #{self}: You should declare is_paranoid before your associations"
|
20
|
+
end
|
21
|
+
|
18
22
|
# This is the real magic. All calls made to this model will append
|
19
23
|
# the conditions deleted_at => nil (or whatever your destroyed_field
|
20
24
|
# and field_not_destroyed are). All exceptions require using
|
@@ -27,6 +31,25 @@ module IsParanoid
|
|
27
31
|
end
|
28
32
|
|
29
33
|
module ClassMethods
|
34
|
+
def is_or_equals_not_destroyed
|
35
|
+
if [nil, 'NULL'].include?(field_not_destroyed)
|
36
|
+
'IS NULL'
|
37
|
+
else
|
38
|
+
"= #{field_not_destroyed}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# ensure that we respect the is_paranoid conditions when being loaded as a has_many :through
|
43
|
+
# NOTE: this only works if is_paranoid is declared before has_many relationships.
|
44
|
+
def has_many(association_id, options = {}, &extension)
|
45
|
+
if options.key?(:through)
|
46
|
+
conditions = "#{options[:through].to_s.pluralize}.#{destroyed_field} #{is_or_equals_not_destroyed}"
|
47
|
+
options[:conditions] = "(" + [options[:conditions], conditions].compact.join(") AND (") + ")"
|
48
|
+
end
|
49
|
+
super
|
50
|
+
end
|
51
|
+
|
52
|
+
|
30
53
|
# Actually delete the model, bypassing the safety net. Because
|
31
54
|
# this method is called internally by Model.delete(id) and on the
|
32
55
|
# delete method in each instance, we don't need to specify those
|
data/spec/is_paranoid_spec.rb
CHANGED
@@ -72,6 +72,24 @@ describe IsParanoid do
|
|
72
72
|
Android.count_with_destroyed.should == 2
|
73
73
|
end
|
74
74
|
|
75
|
+
it "shouldn't have problems with has_many :through relationships" do
|
76
|
+
# TODO: this spec can be cleaner and more specific, replace it later
|
77
|
+
# Dings use a boolean non-standard is_paranoid field
|
78
|
+
# Scratch uses the defaults. Testing both ensures compatibility
|
79
|
+
[[:dings, Ding], [:scratches, Scratch]].each do |method, klass|
|
80
|
+
@r2d2.dings.should == []
|
81
|
+
|
82
|
+
dent = Dent.create(:description => 'really terrible', :android_id => @r2d2.id)
|
83
|
+
item = klass.create(:description => 'quite nasty', :dent_id => dent.id)
|
84
|
+
@r2d2.reload
|
85
|
+
@r2d2.send(method).should == [item]
|
86
|
+
|
87
|
+
dent.destroy
|
88
|
+
@r2d2.reload
|
89
|
+
@r2d2.send(method).should == []
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
75
93
|
it "should not choke has_and_belongs_to_many relationships" do
|
76
94
|
@r2d2.places.should include(@tatooine)
|
77
95
|
@tatooine.destroy
|
@@ -298,5 +316,4 @@ describe IsParanoid do
|
|
298
316
|
uuid.destroy.should be_true
|
299
317
|
end
|
300
318
|
end
|
301
|
-
|
302
319
|
end
|
data/spec/models.rb
CHANGED
@@ -4,14 +4,16 @@ class Person < ActiveRecord::Base #:nodoc:
|
|
4
4
|
end
|
5
5
|
|
6
6
|
class Android < ActiveRecord::Base #:nodoc:
|
7
|
+
is_paranoid
|
7
8
|
validates_uniqueness_of :name
|
8
9
|
has_many :components, :dependent => :destroy
|
9
10
|
has_one :sticker
|
10
11
|
has_many :memories, :foreign_key => 'parent_id'
|
12
|
+
has_many :dents
|
13
|
+
has_many :dings, :through => :dents
|
14
|
+
has_many :scratches, :through => :dents
|
11
15
|
has_and_belongs_to_many :places
|
12
16
|
|
13
|
-
is_paranoid
|
14
|
-
|
15
17
|
# this code is to ensure that our destroy and restore methods
|
16
18
|
# work without triggering before/after_update callbacks
|
17
19
|
before_update :raise_hell
|
@@ -20,6 +22,23 @@ class Android < ActiveRecord::Base #:nodoc:
|
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
25
|
+
class Dent < ActiveRecord::Base #:nodoc:
|
26
|
+
is_paranoid
|
27
|
+
belongs_to :android
|
28
|
+
has_many :dings
|
29
|
+
has_many :scratches
|
30
|
+
end
|
31
|
+
|
32
|
+
class Ding < ActiveRecord::Base #:nodoc:
|
33
|
+
is_paranoid :field => [:not_deleted, true, false]
|
34
|
+
belongs_to :dent
|
35
|
+
end
|
36
|
+
|
37
|
+
class Scratch < ActiveRecord::Base #:nodoc:
|
38
|
+
is_paranoid
|
39
|
+
belongs_to :dent
|
40
|
+
end
|
41
|
+
|
23
42
|
class Component < ActiveRecord::Base #:nodoc:
|
24
43
|
is_paranoid
|
25
44
|
belongs_to :android, :dependent => :destroy
|
data/spec/schema.rb
CHANGED
@@ -7,6 +7,24 @@ ActiveRecord::Schema.define(:version => 20090317164830) do
|
|
7
7
|
t.datetime "updated_at"
|
8
8
|
end
|
9
9
|
|
10
|
+
create_table "dents", :force => true do |t|
|
11
|
+
t.integer "android_id"
|
12
|
+
t.string "description"
|
13
|
+
t.datetime "deleted_at"
|
14
|
+
end
|
15
|
+
|
16
|
+
create_table "dings", :force => true do |t|
|
17
|
+
t.integer "dent_id"
|
18
|
+
t.string "description"
|
19
|
+
t.boolean "not_deleted"
|
20
|
+
end
|
21
|
+
|
22
|
+
create_table "scratches", :force => true do |t|
|
23
|
+
t.integer "dent_id"
|
24
|
+
t.string "description"
|
25
|
+
t.datetime "deleted_at"
|
26
|
+
end
|
27
|
+
|
10
28
|
create_table "androids_places", :force => true, :id => false do |t|
|
11
29
|
t.integer "android_id"
|
12
30
|
t.integer "place_id"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: semanticart-is_paranoid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeffrey Chupp
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-09-
|
12
|
+
date: 2009-09-26 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|