millstone 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ class Master < ActiveRecord::Base
4
+ end
5
+
6
+ class HavingWithDeleted < ActiveRecord::Base
7
+ set_table_name 'havings'
8
+
9
+ acts_as_paranoid
10
+ belongs_to :parent, :class_name => 'ParentHasMaster', :foreign_key => 'parent_id'
11
+ belongs_to :master
12
+ end
13
+
14
+ class HavingWithoutDeleted < ActiveRecord::Base
15
+ set_table_name 'havings'
16
+
17
+ acts_as_paranoid
18
+ belongs_to :parent, :class_name => 'ParentHasMaster', :foreign_key => 'parent_id'
19
+ belongs_to :master
20
+ end
21
+
22
+ class ParentHasMaster < ActiveRecord::Base
23
+ set_table_name 'time_columns'
24
+
25
+ has_many :havings_with_deleted, :class_name => 'HavingWithDeleted', :foreign_key => 'parent_id'
26
+ has_many :havings_without_deleted, :class_name => 'HavingWithoutDeleted', :foreign_key => 'parent_id'
27
+
28
+ has_many :masters_with_deleted, :class_name => 'Master', :through => :havings_with_deleted, :source => :master, :with_deleted => true
29
+ has_many :masters_without_deleted, :class_name => 'Master', :through => :havings_without_deleted, :source => :master
30
+ end
31
+
32
+ describe Millstone::ActiveRecord::Associations::HasManyThroughWithoutDeletedAssociation do
33
+ describe ActiveRecord::Base do
34
+ let(:parent) { ParentHasMaster.create!(:context => "parent") }
35
+ let(:master1) { Master.create!(:context => "master1") }
36
+ let(:master2) { Master.create!(:context => "master2") }
37
+
38
+ describe ".has_many", ":with_deleted => false (default)" do
39
+ before do
40
+ parent.masters_without_deleted << master1
41
+ parent.masters_without_deleted << master2
42
+ parent.masters_without_deleted.delete(master2)
43
+ parent.reload
44
+ end
45
+
46
+ specify { parent.masters_without_deleted.should include master1 }
47
+ specify { parent.masters_without_deleted.should_not include master2 }
48
+ end
49
+
50
+ describe ".has_many", ":with_deleted => true" do
51
+ before do
52
+ parent.masters_with_deleted << master1
53
+ parent.masters_with_deleted << master2
54
+ parent.masters_with_deleted.delete(master2)
55
+ parent.reload
56
+ end
57
+
58
+ specify { parent.masters_with_deleted.should include master1 }
59
+ specify { parent.masters_with_deleted.should include master2 }
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ class MillstoneTimeModel < ActiveRecord::Base
4
+ set_table_name 'time_columns'
5
+ millstone
6
+ end
7
+
8
+ class MillstoneBooleanModel < ActiveRecord::Base
9
+ set_table_name 'boolean_columns'
10
+ millstone :column => :deleted, :type => :boolean
11
+ end
12
+
13
+ describe Millstone::ActiveRecord::Extension do
14
+ describe ActiveRecord::Base do
15
+ let(:record) { klass.create!(:context => "name") }
16
+ let(:deleted_record) { klass.with_deleted.first }
17
+
18
+ shared_examples "execute destroy and destroy!" do
19
+ describe "#destroy" do
20
+ before { record.destroy }
21
+
22
+ specify { deleted_record.should eq record }
23
+ specify { deleted_record.should be_deleted }
24
+ end
25
+
26
+ describe "#destroy!" do
27
+ before { record.destroy! }
28
+ specify { deleted_record.should be_nil }
29
+ end
30
+ end
31
+
32
+ context "as millstone :type => :boolean" do
33
+ let(:klass) { MillstoneBooleanModel }
34
+
35
+ it_behaves_like "execute destroy and destroy!"
36
+
37
+ describe "#destroy" do
38
+ before { record.destroy }
39
+ specify { deleted_record.deleted.should be_true }
40
+ end
41
+ end
42
+
43
+ context "as millstone :type => :time" do
44
+ before { Delorean.time_travel_to 1.hour.ago }
45
+ after { Delorean.back_to_the_present }
46
+
47
+ let(:klass) { MillstoneTimeModel }
48
+
49
+ describe "#destroy" do
50
+ before { record.destroy }
51
+ specify { deleted_record.deleted_at.to_s.should == Time.now.to_s }
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ class MillstoneTimeColumn < ActiveRecord::Base
4
+ set_table_name 'time_columns'
5
+ millstone
6
+ end
7
+
8
+ class MillstoneBooleanColumn < ActiveRecord::Base
9
+ set_table_name 'boolean_columns'
10
+ millstone :column => :deleted, :type => :boolean
11
+ end
12
+
13
+ describe Millstone::ActiveRecord::RelationMethods do
14
+ let (:alive_record) { klass.create!(:context => "alive") }
15
+ let (:hidden_record) { klass.create!(:context => "hidden", klass.millstone_column => klass.millstone_generate_column_value) }
16
+
17
+ describe MillstoneTimeColumn do
18
+ let(:klass) { MillstoneTimeColumn }
19
+
20
+ it_should_behave_like "hide soft deletion marked record"
21
+ it_should_behave_like "execute soft deletion" do
22
+ it "should set time to paranoid value" do
23
+ klass.delete(alive_record)
24
+ klass.with_deleted.find(alive_record).deleted_at.should be_a Time
25
+ end
26
+ end
27
+ it_should_behave_like "execute hard deletion"
28
+ it_should_behave_like "check soft deletion"
29
+ end
30
+
31
+ describe MillstoneBooleanColumn do
32
+ let(:klass) { MillstoneBooleanColumn }
33
+
34
+ it_should_behave_like "hide soft deletion marked record"
35
+ it_should_behave_like "execute soft deletion" do
36
+ it "should set true to paranoid value" do
37
+ klass.delete(alive_record)
38
+ klass.with_deleted.find(alive_record).deleted.should be_true
39
+ end
40
+ end
41
+ it_should_behave_like "execute hard deletion"
42
+ it_should_behave_like "check soft deletion"
43
+ end
44
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ class UniquenessWithDeleted < ActiveRecord::Base
4
+ set_table_name 'time_columns'
5
+
6
+ millstone
7
+ validates_uniqueness_of_with_deleted :context
8
+ end
9
+
10
+ class UniquenessWithoutDeleted < ActiveRecord::Base
11
+ set_table_name 'time_columns'
12
+
13
+ millstone
14
+ validates_uniqueness_of :context
15
+ end
16
+
17
+ describe Millstone::ActiveRecord::Validations::UniquenessWithDeletedValidator do
18
+ describe ActiveRecord::Base do
19
+ describe ".validates_uniqueness_of" do
20
+ let(:alive_record) { UniquenessWithoutDeleted.create(:context => "unique1") }
21
+ let(:hidden_record) do
22
+ hidden_record = UniquenessWithoutDeleted.create(:context => "unique2")
23
+ hidden_record.destroy
24
+ hidden_record
25
+ end
26
+
27
+ specify { UniquenessWithoutDeleted.new(:context => alive_record.context).should_not be_valid }
28
+ specify { UniquenessWithoutDeleted.new(:context => hidden_record.context).should be_valid }
29
+ end
30
+
31
+ describe ".validates_uniqueness_of_with_deleted" do
32
+ let(:alive_record) { UniquenessWithDeleted.create(:context => "unique1") }
33
+ let(:hidden_record) do
34
+ hidden_record = UniquenessWithDeleted.create(:context => "unique2")
35
+ hidden_record.destroy
36
+ hidden_record
37
+ end
38
+
39
+ specify { UniquenessWithDeleted.new(:context => alive_record.context).should_not be_valid }
40
+ specify { UniquenessWithDeleted.new(:context => hidden_record.context).should_not be_valid }
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,25 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $:.unshift(File.dirname(__FILE__))
3
+
4
+ require 'rails'
5
+ require 'active_record'
6
+ require 'action_controller'
7
+ require 'action_view'
8
+ require 'delorean'
9
+ require 'millstone'
10
+
11
+ require 'rspec/rails'
12
+
13
+ # Requires supporting files with custom matchers and macros, etc,
14
+ # in ./support/ and its subdirectories.
15
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
16
+
17
+ RSpec.configure do |config|
18
+ config.include Delorean
19
+ config.mock_with :rspec
20
+ config.fixture_path = File.join(File.dirname(__FILE__), 'fixtures')
21
+ config.use_transactional_fixtures = true
22
+ end
23
+
24
+ CreateTestTables.up
25
+
@@ -0,0 +1,6 @@
1
+ shared_examples "check soft deletion" do
2
+ describe "#deleted?" do
3
+ specify { alive_record.should_not be_deleted }
4
+ specify { hidden_record.should be_deleted }
5
+ end
6
+ end
@@ -0,0 +1,43 @@
1
+ shared_examples "delete alive and hidden record" do
2
+ specify "alive record should be deleted from table" do
3
+ expect { klass.with_deleted.find(alive_record) }.to raise_error(ActiveRecord::RecordNotFound)
4
+ end
5
+
6
+ specify "hidden record should be deleted from table" do
7
+ expect { klass.with_deleted.find(hidden_record) }.to raise_error(ActiveRecord::RecordNotFound)
8
+ end
9
+ end
10
+
11
+ shared_examples "execute hard deletion" do
12
+ describe ".delete!" do
13
+ it_behaves_like "delete alive and hidden record" do
14
+ before do
15
+ klass.delete!([alive_record, hidden_record])
16
+ end
17
+ end
18
+ end
19
+
20
+ describe ".delete_all!" do
21
+ it_behaves_like "delete alive and hidden record" do
22
+ before do
23
+ klass.delete_all!(["id IN (?)", [alive_record, hidden_record]])
24
+ end
25
+ end
26
+ end
27
+
28
+ describe ".destroy!" do
29
+ it_behaves_like "delete alive and hidden record" do
30
+ before do
31
+ klass.destroy!([alive_record, hidden_record])
32
+ end
33
+ end
34
+ end
35
+
36
+ describe ".destroy_all!" do
37
+ it_behaves_like "delete alive and hidden record" do
38
+ before do
39
+ klass.destroy_all!(["id IN (?)", [alive_record, hidden_record]])
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,57 @@
1
+ shared_examples "execute soft deletion" do
2
+ describe ".delete_all" do
3
+ it "should mark deletion to alive record" do
4
+ expect do
5
+ klass.delete_all(:id => alive_record)
6
+ end.should change { klass.with_deleted.find(alive_record).millstone_column_value }
7
+ end
8
+
9
+ it "should not mark deletion to hidden record" do
10
+ expect do
11
+ klass.delete_all(:id => hidden_record)
12
+ end.should_not change { klass.with_deleted.find(hidden_record).millstone_column_value }
13
+ end
14
+ end
15
+
16
+ describe ".delete" do
17
+ it "should mark deletion to alive record" do
18
+ expect do
19
+ klass.delete(alive_record)
20
+ end.should change { klass.with_deleted.find(alive_record).millstone_column_value }
21
+ end
22
+
23
+ it "should not mark deletion to hidden record" do
24
+ expect do
25
+ klass.delete(hidden_record)
26
+ end.should_not change { klass.with_deleted.find(hidden_record).millstone_column_value }
27
+ end
28
+ end
29
+
30
+ describe ".destroy_all" do
31
+ it "should mark deletion to alive record" do
32
+ expect do
33
+ klass.destroy_all(:id => alive_record)
34
+ end.should change { klass.with_deleted.find(alive_record).millstone_column_value }
35
+ end
36
+
37
+ it "should not mark deletion to hidden record" do
38
+ expect do
39
+ klass.destroy_all(:id => hidden_record)
40
+ end.should_not change { klass.with_deleted.find(hidden_record).millstone_column_value }
41
+ end
42
+ end
43
+
44
+ describe ".destroy" do
45
+ it "should mark deletion to alive record" do
46
+ expect do
47
+ klass.destroy(alive_record)
48
+ end.should change { klass.with_deleted.find(alive_record).millstone_column_value }
49
+ end
50
+
51
+ it "should not mark deletion to hidden record" do
52
+ expect do
53
+ klass.destroy(hidden_record)
54
+ end.should raise_error(ActiveRecord::RecordNotFound)
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,98 @@
1
+ shared_examples "hide soft deletion marked record" do
2
+ before do
3
+ klass.delete_all
4
+ 3.times { klass.create!(:context => "alive") }
5
+ 2.times { klass.create!(:context => "hidden", klass.millstone_column => klass.millstone_generate_column_value) }
6
+ end
7
+
8
+ describe ".all" do
9
+ subject { klass.all }
10
+ it { should_not include hidden_record }
11
+ it { should include alive_record }
12
+ end
13
+
14
+ describe ".find" do
15
+ specify { klass.find(alive_record).should_not be_nil }
16
+
17
+ specify do
18
+ expect { klass.find(hidden_record) }.to raise_error(ActiveRecord::RecordNotFound)
19
+ end
20
+
21
+ context "options :with_deleted" do
22
+ specify { klass.find(hidden_record, :with_deleted => true).should_not be_nil }
23
+ specify { klass.find(alive_record, :with_deleted => true).should_not be_nil }
24
+ end
25
+
26
+ context "options :only_deleted" do
27
+ specify { klass.find(hidden_record, :only_deleted => true).should_not be_nil }
28
+
29
+ specify do
30
+ expect { klass.find(alive_record, :only_deleted => true) }.to raise_error(ActiveRecord::RecordNotFound)
31
+ end
32
+ end
33
+ end
34
+
35
+ describe ".count" do
36
+ subject { klass.count }
37
+ it "should return record count without hidden record" do
38
+ should == 3
39
+ end
40
+ end
41
+
42
+ describe ".with_deleted" do
43
+ describe ".all" do
44
+ subject { klass.with_deleted.all }
45
+ it { should include hidden_record }
46
+ it { should include alive_record }
47
+ end
48
+
49
+ describe ".find" do
50
+ context "when specify hidden record" do
51
+ subject { klass.only_deleted.find(hidden_record) }
52
+ it { should eq hidden_record }
53
+ end
54
+
55
+ context "when specify alive record" do
56
+ subject { klass.find(alive_record) }
57
+ it { should eq alive_record }
58
+ end
59
+ end
60
+
61
+ describe ".count" do
62
+ subject { klass.with_deleted.count }
63
+ it "should return all record count" do
64
+ should == 5
65
+ end
66
+ end
67
+ end
68
+
69
+ describe ".only_deleted" do
70
+ describe ".all" do
71
+ subject { klass.only_deleted.all }
72
+ it { should include hidden_record }
73
+ it { should_not include alive_record }
74
+ end
75
+
76
+ describe ".find" do
77
+ context "when specify hidden record" do
78
+ subject { klass.only_deleted.find(hidden_record) }
79
+ it { should eq hidden_record }
80
+ end
81
+
82
+ context "when specify alive record" do
83
+ it "should raise error ActiveRecord::RecordNotFound" do
84
+ expect do
85
+ klass.only_deleted.find(alive_record)
86
+ end.to raise_error(ActiveRecord::RecordNotFound)
87
+ end
88
+ end
89
+ end
90
+
91
+ describe ".count" do
92
+ subject { klass.only_deleted.count }
93
+ it "should return only hidden record count" do
94
+ should == 2
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,49 @@
1
+ require 'active_record'
2
+
3
+ # database connection
4
+ ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => ':memory:'}}
5
+ ActiveRecord::Base.establish_connection('test')
6
+
7
+ class CreateTestTables < ActiveRecord::Migration
8
+ def self.up
9
+ create_table :time_columns, :force => true do |t|
10
+ t.string :context
11
+ t.datetime :deleted_at
12
+ t.timestamps
13
+ end
14
+
15
+ create_table :boolean_columns, :force => true do |t|
16
+ t.string :context
17
+ t.boolean :deleted
18
+ t.timestamps
19
+ end
20
+
21
+ create_table :children, :force => true do |t|
22
+ t.integer :parent_id
23
+ t.string :context
24
+ t.datetime :deleted_at
25
+ t.timestamps
26
+ end
27
+
28
+ create_table :polymorphic_children, :force => true do |t|
29
+ t.string :polymorphous_type
30
+ t.integer :polymorphous_id
31
+ t.string :context
32
+ t.datetime :deleted_at
33
+ t.timestamps
34
+ end
35
+
36
+ create_table :masters, :force => true do |t|
37
+ t.string :context
38
+ t.timestamps
39
+ end
40
+
41
+ create_table :havings, :force => true do |t|
42
+ t.integer :parent_id
43
+ t.integer :master_id
44
+ t.datetime :deleted_at
45
+ t.timestamps
46
+ end
47
+
48
+ end
49
+ end
metadata ADDED
@@ -0,0 +1,196 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: millstone
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Yoshikazu Ozawa
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-08-09 00:00:00 +09:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rails
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 11
30
+ segments:
31
+ - 3
32
+ - 0
33
+ - 6
34
+ version: 3.0.6
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: bundler
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 23
46
+ segments:
47
+ - 1
48
+ - 0
49
+ - 0
50
+ version: 1.0.0
51
+ type: :development
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: sqlite3
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ type: :development
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ name: rspec
69
+ prerelease: false
70
+ requirement: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 15
76
+ segments:
77
+ - 2
78
+ - 0
79
+ - 0
80
+ version: 2.0.0
81
+ type: :development
82
+ version_requirements: *id004
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-rails
85
+ prerelease: false
86
+ requirement: &id005 !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ hash: 15
92
+ segments:
93
+ - 2
94
+ - 0
95
+ - 0
96
+ version: 2.0.0
97
+ type: :development
98
+ version_requirements: *id005
99
+ - !ruby/object:Gem::Dependency
100
+ name: delorean
101
+ prerelease: false
102
+ requirement: &id006 !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ hash: 3
108
+ segments:
109
+ - 0
110
+ version: "0"
111
+ type: :development
112
+ version_requirements: *id006
113
+ description: ActiveRecord plugin which allows you to hide without actually deleting them for Rails3. Millstone is extending ActiveRecord::Relation
114
+ email:
115
+ - yoshikazu.ozawa@gmail.com
116
+ executables: []
117
+
118
+ extensions: []
119
+
120
+ extra_rdoc_files: []
121
+
122
+ files:
123
+ - .gitignore
124
+ - .rspec
125
+ - Gemfile
126
+ - LICENSE
127
+ - README.md
128
+ - Rakefile
129
+ - lib/millstone.rb
130
+ - lib/millstone/active_record/associations.rb
131
+ - lib/millstone/active_record/associations/belongs_to_association.rb
132
+ - lib/millstone/active_record/associations/belongs_to_polymorphic_association.rb
133
+ - lib/millstone/active_record/associations/has_many_through_without_deleted_association.rb
134
+ - lib/millstone/active_record/extension.rb
135
+ - lib/millstone/active_record/relation_methods.rb
136
+ - lib/millstone/active_record/validations/uniqueness_with_deleted.rb
137
+ - millstone.gemspec
138
+ - spec/models/associations/belongs_to_association_spec.rb
139
+ - spec/models/associations/belongs_to_polymorphic_association_spec.rb
140
+ - spec/models/associations/has_many_through_without_deleted_association_spec.rb
141
+ - spec/models/extension_spec.rb
142
+ - spec/models/relation_methods_spec.rb
143
+ - spec/models/validations/uniqueness_with_deleted_spec.rb
144
+ - spec/spec_helper.rb
145
+ - spec/support/examples/check_soft_deletion.rb
146
+ - spec/support/examples/execute_hard_deletion.rb
147
+ - spec/support/examples/execute_soft_deletion.rb
148
+ - spec/support/examples/hide_soft_deletion_marked_record.rb
149
+ - spec/support/migration.rb
150
+ has_rdoc: true
151
+ homepage: https://github.com/relax4u/millstone
152
+ licenses:
153
+ - MIT
154
+ post_install_message:
155
+ rdoc_options: []
156
+
157
+ require_paths:
158
+ - lib
159
+ required_ruby_version: !ruby/object:Gem::Requirement
160
+ none: false
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ hash: 3
165
+ segments:
166
+ - 0
167
+ version: "0"
168
+ required_rubygems_version: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ hash: 3
174
+ segments:
175
+ - 0
176
+ version: "0"
177
+ requirements: []
178
+
179
+ rubyforge_project:
180
+ rubygems_version: 1.3.7
181
+ signing_key:
182
+ specification_version: 3
183
+ summary: ActiveRecord plugin which allows you to hide without actually deleting them for Rails3.
184
+ test_files:
185
+ - spec/models/associations/belongs_to_association_spec.rb
186
+ - spec/models/associations/belongs_to_polymorphic_association_spec.rb
187
+ - spec/models/associations/has_many_through_without_deleted_association_spec.rb
188
+ - spec/models/extension_spec.rb
189
+ - spec/models/relation_methods_spec.rb
190
+ - spec/models/validations/uniqueness_with_deleted_spec.rb
191
+ - spec/spec_helper.rb
192
+ - spec/support/examples/check_soft_deletion.rb
193
+ - spec/support/examples/execute_hard_deletion.rb
194
+ - spec/support/examples/execute_soft_deletion.rb
195
+ - spec/support/examples/hide_soft_deletion_marked_record.rb
196
+ - spec/support/migration.rb