immortal 0.1.7 → 1.0.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.
- data/Gemfile.lock +21 -17
- data/README.md +2 -0
- data/immortal.gemspec +3 -3
- data/lib/immortal.rb +21 -34
- data/spec/immortal_spec.rb +7 -53
- metadata +14 -17
- data/lib/immortal/has_many_through_mortal_association.rb +0 -23
data/Gemfile.lock
CHANGED
@@ -1,28 +1,32 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
immortal (0.1.
|
5
|
-
activerecord (
|
4
|
+
immortal (0.1.6)
|
5
|
+
activerecord (= 3.1.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: http://rubygems.org/
|
9
9
|
specs:
|
10
|
-
activemodel (3.0
|
11
|
-
activesupport (= 3.0
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
10
|
+
activemodel (3.1.0)
|
11
|
+
activesupport (= 3.1.0)
|
12
|
+
bcrypt-ruby (~> 3.0.0)
|
13
|
+
builder (~> 3.0.0)
|
14
|
+
i18n (~> 0.6)
|
15
|
+
activerecord (3.1.0)
|
16
|
+
activemodel (= 3.1.0)
|
17
|
+
activesupport (= 3.1.0)
|
18
|
+
arel (~> 2.2.1)
|
19
|
+
tzinfo (~> 0.3.29)
|
20
|
+
activesupport (3.1.0)
|
21
|
+
multi_json (~> 1.0)
|
22
|
+
arel (2.2.1)
|
23
|
+
bcrypt-ruby (3.0.1)
|
24
|
+
builder (3.0.0)
|
22
25
|
columnize (0.3.2)
|
23
26
|
diff-lcs (1.1.2)
|
24
|
-
i18n (0.
|
27
|
+
i18n (0.6.0)
|
25
28
|
linecache (0.43)
|
29
|
+
multi_json (1.0.3)
|
26
30
|
rspec (2.3.0)
|
27
31
|
rspec-core (~> 2.3.0)
|
28
32
|
rspec-expectations (~> 2.3.0)
|
@@ -36,7 +40,7 @@ GEM
|
|
36
40
|
ruby-debug-base (~> 0.10.4.0)
|
37
41
|
ruby-debug-base (0.10.4)
|
38
42
|
linecache (>= 0.3)
|
39
|
-
sqlite3
|
43
|
+
sqlite3 (1.3.4)
|
40
44
|
tzinfo (0.3.29)
|
41
45
|
|
42
46
|
PLATFORMS
|
@@ -46,4 +50,4 @@ DEPENDENCIES
|
|
46
50
|
immortal!
|
47
51
|
rspec (~> 2.3.0)
|
48
52
|
ruby-debug (~> 0.10.4)
|
49
|
-
sqlite3
|
53
|
+
sqlite3
|
data/README.md
CHANGED
@@ -44,6 +44,8 @@ If you want to improve immortal
|
|
44
44
|
|
45
45
|
## CHANGELOG
|
46
46
|
|
47
|
+
- 1.0.0 Changed the API, made it compatible with Rails 3.1, removed
|
48
|
+
functionality
|
47
49
|
- 0.1.6 Fixing immortal issue 2: with_deleted breaks associations
|
48
50
|
- 0.1.5 Add "without deleted" scope to join model by overriding HasManyThroughAssociation#construct_conditions
|
49
51
|
rather than simply adding to has_many conditions.
|
data/immortal.gemspec
CHANGED
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "immortal"
|
6
|
-
s.version = '0.
|
6
|
+
s.version = '1.0.0'
|
7
7
|
s.platform = Gem::Platform::RUBY
|
8
8
|
s.authors = ["Jordi Romero", "Saimon Moore"]
|
9
9
|
s.email = ["jordi@jrom.net", "saimon@saimonmoore.net"]
|
@@ -16,8 +16,8 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
17
|
s.require_paths = ["lib"]
|
18
18
|
|
19
|
-
s.add_dependency 'activerecord', '
|
19
|
+
s.add_dependency 'activerecord', '3.1.0'
|
20
20
|
s.add_development_dependency 'rspec', '~> 2.3.0'
|
21
|
-
s.add_development_dependency 'sqlite3
|
21
|
+
s.add_development_dependency 'sqlite3'
|
22
22
|
s.add_development_dependency 'ruby-debug', '~> 0.10.4'
|
23
23
|
end
|
data/lib/immortal.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'immortal/has_many_through_mortal_association'
|
2
|
-
|
3
1
|
module Immortal
|
4
2
|
|
5
3
|
def self.included(base)
|
@@ -12,11 +10,7 @@ module Immortal
|
|
12
10
|
# from the join model
|
13
11
|
def has_many_mortal(association_id, options = {}, &extension)
|
14
12
|
has_many_immortal(association_id, options, &extension).tap do
|
15
|
-
|
16
|
-
reflection = reflect_on_association(association_id)
|
17
|
-
collection_reader_method(reflection, Immortal::HasManyThroughMortalAssociation)
|
18
|
-
collection_accessor_methods(reflection, Immortal::HasManyThroughMortalAssociation, false)
|
19
|
-
end
|
13
|
+
# FIXME This must be re-implemented after the ActiveRecord internals refactor in 3.1
|
20
14
|
end
|
21
15
|
end
|
22
16
|
|
@@ -35,32 +29,38 @@ module Immortal
|
|
35
29
|
self.included_modules.include?(::Immortal::InstanceMethods)
|
36
30
|
end
|
37
31
|
|
38
|
-
def
|
39
|
-
|
32
|
+
def without_default_scope
|
33
|
+
with_exclusive_scope do
|
34
|
+
yield
|
35
|
+
end
|
40
36
|
end
|
41
37
|
|
42
|
-
def
|
43
|
-
|
44
|
-
where_sql_clauses = filter_undeleted_where_clauses
|
45
|
-
where_sql_clauses.concat unscoped.where(deleted_clause).where_clauses
|
46
|
-
|
47
|
-
except(:where).where(where_sql_clauses.join(" AND "))
|
38
|
+
def exists?(id = false)
|
39
|
+
where(:deleted => false).exists?(id)
|
48
40
|
end
|
49
41
|
|
50
42
|
def count_with_deleted(*args)
|
51
|
-
|
43
|
+
without_default_scope do
|
44
|
+
count(*args)
|
45
|
+
end
|
52
46
|
end
|
53
47
|
|
54
48
|
def count_only_deleted(*args)
|
55
|
-
|
49
|
+
without_default_scope do
|
50
|
+
where(:deleted => true).count(*args)
|
51
|
+
end
|
56
52
|
end
|
57
53
|
|
58
54
|
def find_with_deleted(*args)
|
59
|
-
|
55
|
+
without_default_scope do
|
56
|
+
find(*args)
|
57
|
+
end
|
60
58
|
end
|
61
59
|
|
62
60
|
def find_only_deleted(*args)
|
63
|
-
|
61
|
+
without_default_scope do
|
62
|
+
where(:deleted => true).find(*args)
|
63
|
+
end
|
64
64
|
end
|
65
65
|
|
66
66
|
def immortal_delete_all(conditions = nil)
|
@@ -72,24 +72,11 @@ module Immortal
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def undeleted_clause_sql
|
75
|
-
unscoped.where(arel_table[:deleted].eq(nil).or(arel_table[:deleted].eq(false))).
|
75
|
+
unscoped.where(arel_table[:deleted].eq(nil).or(arel_table[:deleted].eq(false))).constraints.first.to_sql
|
76
76
|
end
|
77
77
|
|
78
78
|
def deleted_clause_sql
|
79
|
-
unscoped.where(arel_table[:deleted].eq(true)).
|
80
|
-
end
|
81
|
-
|
82
|
-
private
|
83
|
-
|
84
|
-
def filter_undeleted_where_clauses
|
85
|
-
where_clauses = scoped.arel.send(:where_clauses)
|
86
|
-
|
87
|
-
#Yes it's an ugly hack but I couldn't find a cleaner way of doing this
|
88
|
-
filtered_clauses = where_clauses.dup.map do |clause|
|
89
|
-
clause.gsub(/(\s+AND\s+)?\("?`?(\w+)`?"?."?`?deleted`?"?\sIS\sNULL[^\)]+\)/, '')
|
90
|
-
end.map {|cl| cl.gsub("()", '')}.select {|cl| !cl.empty?}
|
91
|
-
|
92
|
-
filtered_clauses
|
79
|
+
unscoped.where(arel_table[:deleted].eq(true)).constraints.first.to_sql
|
93
80
|
end
|
94
81
|
|
95
82
|
end
|
data/spec/immortal_spec.rb
CHANGED
@@ -38,12 +38,6 @@ describe Immortal do
|
|
38
38
|
ImmortalModel.all.should be_empty
|
39
39
|
end
|
40
40
|
|
41
|
-
it "should find deleted records using scope" do
|
42
|
-
@m.destroy
|
43
|
-
ImmortalModel.with_deleted.first.should == @m
|
44
|
-
ImmortalModel.with_deleted.all.should include(@m)
|
45
|
-
end
|
46
|
-
|
47
41
|
it "should find deleted records using the old method" do
|
48
42
|
ImmortalModel.find_with_deleted(@m.id).should == @m
|
49
43
|
@m.destroy
|
@@ -53,12 +47,10 @@ describe Immortal do
|
|
53
47
|
it "should count undeleted records by default" do
|
54
48
|
@m2 = ImmortalModel.create! :title => 'testing immortal again'
|
55
49
|
ImmortalModel.count_only_deleted.should == 0
|
56
|
-
ImmortalModel.only_deleted.count.should == 0
|
57
50
|
|
58
51
|
@m.destroy
|
59
52
|
|
60
53
|
ImmortalModel.count_only_deleted.should == 1
|
61
|
-
ImmortalModel.only_deleted.count.should == 1
|
62
54
|
end
|
63
55
|
|
64
56
|
it "should find only deleted records" do
|
@@ -67,19 +59,12 @@ describe Immortal do
|
|
67
59
|
ImmortalModel.find_only_deleted(@m.id)
|
68
60
|
}.to raise_error(ActiveRecord::RecordNotFound)
|
69
61
|
|
70
|
-
expect {
|
71
|
-
ImmortalModel.only_deleted.find(@m.id)
|
72
|
-
}.to raise_error(ActiveRecord::RecordNotFound)
|
73
|
-
|
74
62
|
@m.destroy
|
75
63
|
|
76
64
|
ImmortalModel.find_only_deleted(@m.id).should == @m
|
77
65
|
expect {
|
78
66
|
ImmortalModel.find_only_deleted(@m2.id)
|
79
67
|
}.to raise_error(ActiveRecord::RecordNotFound)
|
80
|
-
|
81
|
-
ImmortalModel.only_deleted.should include(@m)
|
82
|
-
ImmortalModel.only_deleted.should_not include(@m2)
|
83
68
|
end
|
84
69
|
|
85
70
|
it "should be able to count undeleted records" do
|
@@ -95,7 +80,6 @@ describe Immortal do
|
|
95
80
|
@m2 = ImmortalModel.create! :title => 'testing immortal again'
|
96
81
|
@m.destroy
|
97
82
|
ImmortalModel.count_with_deleted.should == 2
|
98
|
-
ImmortalModel.with_deleted.count.should == 2
|
99
83
|
end
|
100
84
|
|
101
85
|
it "should not exist if deleted" do
|
@@ -152,7 +136,7 @@ describe Immortal do
|
|
152
136
|
it "should immortally delete all records with delete_all!" do
|
153
137
|
expect {
|
154
138
|
ImmortalModel.delete_all!
|
155
|
-
}.to change(ImmortalModel
|
139
|
+
}.to change(ImmortalModel, :count_with_deleted).by(-1)
|
156
140
|
end
|
157
141
|
|
158
142
|
it "should know if it's deleted" do
|
@@ -163,7 +147,7 @@ describe Immortal do
|
|
163
147
|
|
164
148
|
it "should be recoverable" do
|
165
149
|
@m.destroy
|
166
|
-
@m = ImmortalModel.
|
150
|
+
@m = ImmortalModel.find_with_deleted(@m.id)
|
167
151
|
@m.recover!
|
168
152
|
@m.should_not be_frozen
|
169
153
|
@m.should_not be_changed
|
@@ -207,41 +191,11 @@ describe Immortal do
|
|
207
191
|
end
|
208
192
|
|
209
193
|
it "should properly generate joins" do
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
m1 = ImmortalModel.create! :title => 'previously created model'
|
216
|
-
n1 = ImmortalNode.create! :title => 'previously created association'
|
217
|
-
j1 = ImmortalJoin.create! :immortal_model => m1, :immortal_node => n1
|
218
|
-
|
219
|
-
@n = ImmortalNode.create! :title => 'testing association'
|
220
|
-
@join = ImmortalJoin.create! :immortal_model => @m, :immortal_node => @n
|
221
|
-
|
222
|
-
@join.destroy
|
223
|
-
|
224
|
-
@m.nodes.count.should == 0
|
225
|
-
@n.joins.count.should == 0
|
226
|
-
|
227
|
-
@m.nodes.with_deleted.count.should == 1
|
228
|
-
@n.joins.with_deleted.count.should == 1
|
194
|
+
join_sql1 = 'INNER JOIN "immortal_joins" ON "immortal_joins"."immortal_node_id" = "immortal_nodes"."id"'
|
195
|
+
join_sql2 = 'INNER JOIN "immortal_models" ON "immortal_models"."id" = "immortal_joins"."immortal_model_id"'
|
196
|
+
generated_sql = ImmortalNode.joins(:immortal_models).to_sql
|
197
|
+
generated_sql.should include(join_sql1)
|
198
|
+
generated_sql.should include(join_sql2)
|
229
199
|
end
|
230
200
|
|
231
|
-
it "should not unscope associations when using only_deleted scope" do
|
232
|
-
m1 = ImmortalModel.create! :title => 'previously created model'
|
233
|
-
n1 = ImmortalNode.create! :title => 'previously created association'
|
234
|
-
j1 = ImmortalJoin.create! :immortal_model => m1, :immortal_node => n1
|
235
|
-
|
236
|
-
@n = ImmortalNode.create! :title => 'testing association'
|
237
|
-
@join = ImmortalJoin.create! :immortal_model => @m, :immortal_node => @n
|
238
|
-
|
239
|
-
@join.destroy
|
240
|
-
|
241
|
-
@m.nodes.count.should == 0
|
242
|
-
@n.joins.count.should == 0
|
243
|
-
|
244
|
-
@m.nodes.only_deleted.count.should == 1
|
245
|
-
@n.joins.only_deleted.count.should == 1
|
246
|
-
end
|
247
201
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: immortal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
|
-
- 0
|
8
7
|
- 1
|
9
|
-
-
|
10
|
-
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jordi Romero
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-
|
19
|
+
date: 2011-09-28 00:00:00 +02:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -25,14 +25,14 @@ dependencies:
|
|
25
25
|
requirement: &id001 !ruby/object:Gem::Requirement
|
26
26
|
none: false
|
27
27
|
requirements:
|
28
|
-
- -
|
28
|
+
- - "="
|
29
29
|
- !ruby/object:Gem::Version
|
30
|
-
hash:
|
30
|
+
hash: 3
|
31
31
|
segments:
|
32
32
|
- 3
|
33
|
+
- 1
|
33
34
|
- 0
|
34
|
-
|
35
|
-
version: 3.0.5
|
35
|
+
version: 3.1.0
|
36
36
|
type: :runtime
|
37
37
|
version_requirements: *id001
|
38
38
|
- !ruby/object:Gem::Dependency
|
@@ -52,19 +52,17 @@ dependencies:
|
|
52
52
|
type: :development
|
53
53
|
version_requirements: *id002
|
54
54
|
- !ruby/object:Gem::Dependency
|
55
|
-
name: sqlite3
|
55
|
+
name: sqlite3
|
56
56
|
prerelease: false
|
57
57
|
requirement: &id003 !ruby/object:Gem::Requirement
|
58
58
|
none: false
|
59
59
|
requirements:
|
60
|
-
- -
|
60
|
+
- - ">="
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
hash:
|
62
|
+
hash: 3
|
63
63
|
segments:
|
64
|
-
-
|
65
|
-
|
66
|
-
- 2
|
67
|
-
version: 1.3.2
|
64
|
+
- 0
|
65
|
+
version: "0"
|
68
66
|
type: :development
|
69
67
|
version_requirements: *id003
|
70
68
|
- !ruby/object:Gem::Dependency
|
@@ -101,7 +99,6 @@ files:
|
|
101
99
|
- Rakefile
|
102
100
|
- immortal.gemspec
|
103
101
|
- lib/immortal.rb
|
104
|
-
- lib/immortal/has_many_through_mortal_association.rb
|
105
102
|
- spec/immortal_spec.rb
|
106
103
|
- spec/spec_helper.rb
|
107
104
|
has_rdoc: true
|
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'active_record'
|
2
|
-
|
3
|
-
module Immortal
|
4
|
-
|
5
|
-
class HasManyThroughMortalAssociation < ActiveRecord::Associations::HasManyThroughAssociation
|
6
|
-
protected
|
7
|
-
|
8
|
-
def construct_conditions
|
9
|
-
klass = @reflection.through_reflection.klass
|
10
|
-
return super unless klass.respond_to?(:immortal?) && klass.immortal?
|
11
|
-
table_name = @reflection.through_reflection.quoted_table_name
|
12
|
-
conditions = construct_quoted_owner_attributes(@reflection.through_reflection).map do |attr, value|
|
13
|
-
"#{table_name}.#{attr} = #{value}"
|
14
|
-
end
|
15
|
-
|
16
|
-
deleted_conditions = ["#{table_name}.deleted IS NULL OR #{table_name}.deleted = ?", false]
|
17
|
-
conditions << klass.send(:sanitize_sql, deleted_conditions)
|
18
|
-
conditions << sql_conditions if sql_conditions
|
19
|
-
"(" + conditions.join(') AND (') + ")"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|