joshbuddy-has_many_versions 0.0.4 → 0.0.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/Rakefile +41 -0
- data/VERSION.yml +1 -1
- data/lib/has_many_versions.rb +32 -14
- data/rails/init.rb +1 -0
- data/spec/history_spec.rb +37 -0
- data/spec/update_spec.rb +1 -1
- metadata +8 -5
data/Rakefile
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "has_many_versions"
|
8
|
+
gem.summary = %Q{Versioning for has_many relationships}
|
9
|
+
gem.email = "joshbuddy@gmail.com"
|
10
|
+
gem.homepage = "http://github.com/joshbuddy/has_many_versions"
|
11
|
+
gem.authors = ["Joshua Hull"]
|
12
|
+
gem.files = FileList["[A-Z]*", "{lib,spec,rails,bin}/**/*.rb", 'spec/database.yml', 'spec/spec.opts']
|
13
|
+
end
|
14
|
+
rescue LoadError
|
15
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
16
|
+
end
|
17
|
+
|
18
|
+
require 'rake/rdoctask'
|
19
|
+
Rake::RDocTask.new do |rdoc|
|
20
|
+
rdoc.rdoc_dir = 'rdoc'
|
21
|
+
rdoc.title = 'has_many_versions'
|
22
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
23
|
+
rdoc.rdoc_files.include('README*')
|
24
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
25
|
+
end
|
26
|
+
|
27
|
+
require 'spec/rake/spectask'
|
28
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
29
|
+
spec.libs << 'lib' << 'spec'
|
30
|
+
spec.spec_opts << "--options" << "spec/spec.opts"
|
31
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Run all examples with RCov"
|
35
|
+
Spec::Rake::SpecTask.new('spec_with_rcov') do |t|
|
36
|
+
t.spec_files = FileList['spec/**/*.rb']
|
37
|
+
t.rcov = true
|
38
|
+
t.rcov_opts = ['--exclude', 'spec']
|
39
|
+
end
|
40
|
+
|
41
|
+
task :default => :spec
|
data/VERSION.yml
CHANGED
data/lib/has_many_versions.rb
CHANGED
@@ -8,6 +8,8 @@ end
|
|
8
8
|
|
9
9
|
module HasManyVersions
|
10
10
|
|
11
|
+
HistoryItem = Struct.new(:version, :state)
|
12
|
+
|
11
13
|
def upgrade_proxy_object
|
12
14
|
proxy_owner.transaction do
|
13
15
|
new_version = proxy_owner.version + 1
|
@@ -28,21 +30,25 @@ module HasManyVersions
|
|
28
30
|
|
29
31
|
upgrade_proxy_object do |new_version|
|
30
32
|
delete_records_without_versioning_transaction(new_version, @target.select { |v| !other.include?(v) })
|
31
|
-
add_records_without_versioning_transaction(new_version,
|
33
|
+
add_records_without_versioning_transaction(new_version, other_array.select { |v| !current.include?(v) }, @target.select { |v| !other.include?(v) }.collect(&:id))
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
35
|
-
def add_records_without_versioning_transaction(new_version,
|
36
|
-
changing_records = flatten_deeper(records).select{|r|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
37
|
+
def add_records_without_versioning_transaction(new_version, records, excluded_ids = [])
|
38
|
+
changing_records = flatten_deeper(records).select{ |r|
|
39
|
+
(!r.new_record? && (r.changed? || (r.version != (new_version - 1))))
|
40
|
+
}
|
41
|
+
excluded_ids.concat(changing_records.collect(&:id)) unless changing_records.empty?
|
42
|
+
excluded_ids.empty? ?
|
43
|
+
proxy_reflection.klass.update_all(
|
44
|
+
['version = ?', new_version],
|
45
|
+
["#{proxy_reflection.primary_key_name} = ? and version = ?", proxy_owner.id, new_version - 1]
|
46
|
+
) : proxy_reflection.klass.update_all(
|
47
|
+
['version = ?', new_version],
|
48
|
+
["#{proxy_reflection.primary_key_name} = ? and version = ? and #{proxy_reflection.klass.primary_key} not in (?)", proxy_owner.id, new_version - 1, excluded_ids]
|
49
|
+
)
|
44
50
|
records = flatten_deeper(records).collect do |r|
|
45
|
-
if
|
51
|
+
if changing_records.include?(r)
|
46
52
|
new_r = r.clone
|
47
53
|
new_r.from_version = r.id if new_r.respond_to?(:from_version=)
|
48
54
|
new_r
|
@@ -51,7 +57,7 @@ module HasManyVersions
|
|
51
57
|
end
|
52
58
|
end
|
53
59
|
flatten_deeper(records).each do |record|
|
54
|
-
record.initial_version = proxy_owner.version if record.new_record?
|
60
|
+
record.initial_version = proxy_owner.version if record.initial_version.nil? or record.new_record?
|
55
61
|
record.version = proxy_owner.version
|
56
62
|
end
|
57
63
|
__concat__(*records)
|
@@ -60,7 +66,7 @@ module HasManyVersions
|
|
60
66
|
|
61
67
|
def <<(*records)
|
62
68
|
upgrade_proxy_object do |new_version|
|
63
|
-
add_records_without_versioning_transaction(new_version,
|
69
|
+
add_records_without_versioning_transaction(new_version, records)
|
64
70
|
end
|
65
71
|
end
|
66
72
|
|
@@ -83,9 +89,21 @@ module HasManyVersions
|
|
83
89
|
'%s.version = #{version}' % [proxy_reflection.quoted_table_name])
|
84
90
|
end
|
85
91
|
|
92
|
+
def history(from = [proxy_owner.version - 10, 1].max, to = proxy_owner.version)
|
93
|
+
history_items = proxy_reflection.klass.find(:all, :conditions => ["#{proxy_reflection.primary_key_name} = ? and version >= ? and initial_version <= ?", proxy_owner.id, from, to])
|
94
|
+
to = proxy_owner.version if to > proxy_owner.version
|
95
|
+
from = 1 if from < 1
|
96
|
+
(from..to).collect do |version|
|
97
|
+
HistoryItem.new(version, history_items.select { |item|
|
98
|
+
item.initial_version <= version && item.version >= version
|
99
|
+
})
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
86
103
|
def rollback(target_version = proxy_owner.version - 1)
|
104
|
+
return if target_version == proxy_owner.version
|
87
105
|
upgrade_proxy_object do |new_version|
|
88
|
-
proxy_reflection.klass.find(:all, :conditions => [
|
106
|
+
proxy_reflection.klass.find(:all, :conditions => ["#{proxy_reflection.primary_key_name} = ? and initial_version <= ? and version >= ?", proxy_owner.id, target_version, target_version]).each do |new_record|
|
89
107
|
new_record = new_record.clone
|
90
108
|
new_record.initial_version = new_version
|
91
109
|
new_record.version = new_version
|
data/rails/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
autoload :HasManyVersions, 'lib/has_many_versions'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe "HasManyVersions history" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
Database.reset!
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should give you a history" do
|
10
|
+
Database.reset!(true)
|
11
|
+
jasper = Author.new(:name => 'Jasper Fforde')
|
12
|
+
|
13
|
+
books = (1..100).collect do |i|
|
14
|
+
book = Book.new(:name => "Book #{i}", :id => i)
|
15
|
+
book.save!
|
16
|
+
book
|
17
|
+
end
|
18
|
+
jasper.save!
|
19
|
+
titles = [[]]
|
20
|
+
jasper.books = [Book.find(1), Book.find(10), Book.find(11), Book.find(23), Book.find(99)]
|
21
|
+
titles << jasper.books.collect(&:name)
|
22
|
+
jasper.books = [Book.find(1), Book.find(10), Book.find(12), Book.find(25), Book.find(94)]
|
23
|
+
titles << jasper.books.collect(&:name)
|
24
|
+
jasper.books = [Book.find(1), Book.find(10), Book.find(12), Book.find(25), Book.find(94), Book.find(87)]
|
25
|
+
titles << jasper.books.collect(&:name)
|
26
|
+
jasper.books = [Book.find(2), Book.find(4), Book.find(5)]
|
27
|
+
titles << jasper.books.collect(&:name)
|
28
|
+
jasper.books = [Book.find(1), Book.find(10), Book.find(11), Book.find(23), Book.find(99)]
|
29
|
+
titles << jasper.books.collect(&:name)
|
30
|
+
|
31
|
+
jasper.books.history.each do |history|
|
32
|
+
history.state.collect(&:name).should == titles.shift
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
data/spec/update_spec.rb
CHANGED
@@ -51,7 +51,7 @@ describe "HasManyVersions updating" do
|
|
51
51
|
|
52
52
|
jasper.books = [shades_of_grey2, eyre_affair]
|
53
53
|
jasper.version.should == 3
|
54
|
-
|
54
|
+
jasper.books.collect(&:name).should == ['The Eyre Affair', 'Shades of Grey 2']
|
55
55
|
jasper.books.rollback
|
56
56
|
jasper.books.collect(&:name).should == ['The Eyre Affair', 'Shades of Grey']
|
57
57
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: joshbuddy-has_many_versions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Hull
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-04-
|
12
|
+
date: 2009-04-22 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -23,17 +23,20 @@ extra_rdoc_files:
|
|
23
23
|
- README.rdoc
|
24
24
|
- LICENSE
|
25
25
|
files:
|
26
|
+
- LICENSE
|
27
|
+
- Rakefile
|
26
28
|
- README.rdoc
|
27
29
|
- VERSION.yml
|
28
30
|
- lib/has_many_versions.rb
|
29
31
|
- spec/add_spec.rb
|
30
|
-
- spec/database.yml
|
31
32
|
- spec/delete_spec.rb
|
33
|
+
- spec/history_spec.rb
|
32
34
|
- spec/rollback_spec.rb
|
33
|
-
- spec/spec.opts
|
34
35
|
- spec/spec_helper.rb
|
35
36
|
- spec/update_spec.rb
|
36
|
-
-
|
37
|
+
- rails/init.rb
|
38
|
+
- spec/database.yml
|
39
|
+
- spec/spec.opts
|
37
40
|
has_rdoc: true
|
38
41
|
homepage: http://github.com/joshbuddy/has_many_versions
|
39
42
|
post_install_message:
|