has_versions 0.4.9 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/Rakefile +7 -24
  2. data/has_versions.gemspec +5 -6
  3. data/lib/has_versions/attributes.rb +3 -3
  4. data/lib/has_versions/configuration.rb +0 -1
  5. data/lib/has_versions/reset.rb +10 -4
  6. data/lib/has_versions/version_methods/diff.rb +40 -0
  7. data/lib/has_versions/version_methods/log.rb +45 -0
  8. data/lib/has_versions/versioned.rb +9 -12
  9. data/lib/has_versions.rb +8 -9
  10. data/test/has_versions/attributes_test.rb +15 -10
  11. data/test/has_versions/configuration_test.rb +12 -0
  12. data/test/has_versions/reset_test.rb +29 -0
  13. data/test/has_versions/version_methods/diff_test.rb +68 -0
  14. data/test/has_versions/version_methods/log_test.rb +33 -0
  15. data/test/has_versions/versioned_test.rb +27 -0
  16. data/test/helper.rb +6 -0
  17. data/test/support/test_model.rb +21 -0
  18. data/test/support/test_version.rb +15 -0
  19. metadata +24 -96
  20. data/lib/has_versions/apply/simple.rb +0 -34
  21. data/lib/has_versions/apply.rb +0 -9
  22. data/lib/has_versions/diff/simple.rb +0 -27
  23. data/lib/has_versions/diff.rb +0 -7
  24. data/lib/has_versions/merge/always_conflicted.rb +0 -9
  25. data/lib/has_versions/merge/base.rb +0 -22
  26. data/lib/has_versions/merge/choose_first.rb +0 -9
  27. data/lib/has_versions/merge/diff3.rb +0 -66
  28. data/lib/has_versions/merge/fast_forward.rb +0 -34
  29. data/lib/has_versions/merge/merge_base.rb +0 -75
  30. data/lib/has_versions/merge/octopus.rb +0 -42
  31. data/lib/has_versions/merge/three_way.rb +0 -53
  32. data/lib/has_versions/merge.rb +0 -32
  33. data/lib/has_versions/reset/simple.rb +0 -19
  34. data/spec/has_versions/apply_spec.rb +0 -33
  35. data/spec/has_versions/configuration_spec.rb +0 -33
  36. data/spec/has_versions/diff_spec.rb +0 -40
  37. data/spec/has_versions/merge/diff3_spec.rb +0 -29
  38. data/spec/has_versions/merge/merge_base_spec.rb +0 -61
  39. data/spec/has_versions/merge/octopus_spec.rb +0 -74
  40. data/spec/has_versions/merge/three_way_spec.rb +0 -57
  41. data/spec/has_versions/reset_spec.rb +0 -40
  42. data/spec/has_versions/stage_spec.rb +0 -17
  43. data/spec/has_versions/versioned_spec.rb +0 -60
  44. data/spec/spec_helper.rb +0 -17
  45. data/spec/support/matchers/be_a_uuid.rb +0 -7
  46. data/spec/support/version.rb +0 -17
  47. data/test/test_helper.rb +0 -3
data/Rakefile CHANGED
@@ -1,29 +1,12 @@
1
1
  require 'bundler/setup'
2
2
  Bundler::GemHelper.install_tasks
3
3
 
4
- require 'rspec/core'
5
- require 'rspec/core/rake_task'
6
- RSpec::Core::RakeTask.new(:spec) do |spec|
7
- spec.pattern = FileList['spec/**/*_spec.rb']
8
- end
9
-
10
- # require 'cucumber/rake/task'
11
- # Cucumber::Rake::Task.new(:features)
12
-
13
- # require 'reek/rake/task'
14
- # Reek::Rake::Task.new do |t|
15
- # t.fail_on_error = true
16
- # t.verbose = false
17
- # t.source_files = 'lib/**/*.rb'
18
- # end
4
+ require 'rake/testtask'
19
5
 
20
- # require 'roodi'
21
- # require 'roodi_task'
22
- # RoodiTask.new do |t|
23
- # t.verbose = false
24
- # end
25
-
26
- task :default => :spec
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << 'lib'
8
+ t.libs << 'test'
9
+ t.pattern = 'test/**/*_test.rb'
10
+ t.verbose = false
11
+ end
27
12
 
28
- # require 'yard'
29
- # YARD::Rake::YardocTask.new
data/has_versions.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  Gem::Specification.new do |s|
3
3
  s.name = "has_versions"
4
- s.version = '0.4.9'
4
+ s.version = '0.5.0'
5
5
 
6
6
  s.platform = Gem::Platform::RUBY
7
7
  s.authors = ["Grant Rodgers"]
@@ -23,9 +23,8 @@ Gem::Specification.new do |s|
23
23
  ]
24
24
  s.licenses = ["MIT"]
25
25
 
26
- s.add_runtime_dependency("i18n", [">= 0"])
27
- s.add_runtime_dependency("activesupport", ["~> 3.0"])
28
- s.add_runtime_dependency("simple_uuid", [">= 0"])
29
- s.add_development_dependency("rspec", ["~> 2.0"])
30
- s.add_development_dependency("yard", ["~> 0.6.0"])
26
+ # s.add_runtime_dependency("i18n", [">= 0"])
27
+ s.add_runtime_dependency("activesupport", "~> 3.2")
28
+ s.add_development_dependency("rake")
29
+ # s.add_runtime_dependency("simple_uuid", [">= 0"])
31
30
  end
@@ -3,14 +3,14 @@ module HasVersions
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  module ClassMethods
6
- def versioned_fields
6
+ def versioned_attributes
7
7
  versioning_configuration.attributes
8
8
  end
9
9
  end
10
10
 
11
11
  def versioned_attributes
12
- self.class.versioned_fields.inject({}) do |memo, attribute|
13
- memo[attribute] = versioning_encode_value(attribute, self[attribute])
12
+ self.class.versioned_attributes.inject({}) do |memo, attribute|
13
+ memo[attribute] = versioning_encode_value(attribute, send(attribute))
14
14
  memo
15
15
  end
16
16
  end
@@ -1,5 +1,4 @@
1
1
  module HasVersions
2
-
3
2
  class Configuration
4
3
  attr_accessor :attributes
5
4
 
@@ -1,15 +1,21 @@
1
1
  module HasVersions
2
2
  module Reset
3
- extend ActiveSupport::Autoload
3
+ extend ActiveSupport::Concern
4
4
 
5
- autoload :Simple
6
-
7
- module FromVersion
5
+ module ClassMethods
8
6
  def from_version(version)
9
7
  new.tap do |object|
10
8
  object.reset!(version)
11
9
  end
12
10
  end
13
11
  end
12
+
13
+ def reset!(version)
14
+ self.class.versioned_attributes.each do |attribute|
15
+ value = versioning_decode_value(attribute, version.snapshot[attribute])
16
+ send("#{attribute}=", value)
17
+ end
18
+ self
19
+ end
14
20
  end
15
21
  end
@@ -0,0 +1,40 @@
1
+ module HasVersions
2
+ module VersionMethods
3
+ module Diff
4
+ def diff(original = parent)
5
+ original_snapshot = original.nil? ? {} : original.decoded_snapshot
6
+
7
+ output = {}
8
+ decoded_snapshot.each do |attribute, new_value|
9
+ original_value = original_snapshot[attribute]
10
+
11
+ if original_value != new_value
12
+ output[attribute] = [original_value, new_value]
13
+ end
14
+ end
15
+
16
+ output
17
+ end
18
+
19
+ def modified_attributes
20
+ diff.keys
21
+ end
22
+
23
+ def different_attributes
24
+ modified_attributes.select do |attribute|
25
+ target.send(attribute) != decoded_snapshot[attribute]
26
+ end
27
+ end
28
+
29
+ def decoded_snapshot
30
+ @decoded_snapshot ||= begin
31
+ decoded = {}
32
+ target.class.versioned_attributes.each do |attribute|
33
+ decoded[attribute] = target.versioning_decode_value(attribute, snapshot[attribute])
34
+ end
35
+ decoded
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,45 @@
1
+ module HasVersions
2
+ module VersionMethods
3
+ class LogCollection
4
+ include Enumerable
5
+
6
+ def initialize(version)
7
+ @version = version
8
+ end
9
+
10
+ def walk
11
+ walker = Walker.new(@version)
12
+ while v = walker.next
13
+ yield v
14
+ end
15
+ end
16
+ alias_method :each, :walk
17
+
18
+ def all
19
+ all = []
20
+ walk { |v| all << v }
21
+ all
22
+ end
23
+ alias_method :to_a, :all
24
+
25
+ class Walker
26
+ attr_accessor :current_version
27
+ def initialize(version)
28
+ self.current_version = version
29
+ end
30
+
31
+ def next
32
+ version = self.current_version
33
+ self.current_version = version.try(:parent)
34
+ version
35
+ end
36
+ end
37
+ end
38
+
39
+ module Log
40
+ def log
41
+ @log ||= LogCollection.new(self)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -7,33 +7,30 @@ module HasVersions
7
7
  class_attribute :version_class
8
8
 
9
9
  include HasVersions::Attributes
10
- include HasVersions::Reset::Simple
11
- include HasVersions::Diff::Simple
12
- extend HasVersions::Reset::FromVersion
10
+ include HasVersions::Reset
13
11
  end
14
12
 
15
13
  module ClassMethods
16
14
  def has_versions(version_class, &block)
17
15
  self.versioning_configuration = HasVersions::Configuration.new(&block)
18
16
  self.version_class = version_class
17
+ version_class.class_eval do
18
+ include HasVersions::VersionMethods::Diff
19
+ include HasVersions::VersionMethods::Log
20
+ end
19
21
  end
20
22
 
21
23
  def versioned_attribute(name)
22
24
  self.versioning_configuration ||= HasVersions::Configuration.new
23
25
  versioning_configuration.attribute(name)
24
26
  end
25
-
26
- def is_versioned?
27
- !versioning_configuration.blank?
28
- end
29
27
  end
30
28
 
31
- # generates a version from the current object
32
29
  def to_version
33
- version_class.new.tap do |version|
34
- version.snapshot = versioned_attributes
35
- version.target = self
36
- end
30
+ version = version_class.new
31
+ version.snapshot = versioned_attributes
32
+ version.target = self
33
+ version
37
34
  end
38
35
  end
39
36
  end
data/lib/has_versions.rb CHANGED
@@ -3,16 +3,10 @@ require 'active_support/all'
3
3
  module HasVersions
4
4
  extend ActiveSupport::Autoload
5
5
 
6
- autoload :Configuration
7
- autoload :Versioned
8
6
  autoload :Attributes
9
-
10
- autoload :Stage
11
-
12
- autoload :Apply
13
- autoload :Diff
14
- autoload :Merge
7
+ autoload :Configuration
15
8
  autoload :Reset
9
+ autoload :Versioned
16
10
 
17
11
  module Orm
18
12
  extend ActiveSupport::Autoload
@@ -20,7 +14,12 @@ module HasVersions
20
14
  autoload :CassandraObject
21
15
  end
22
16
 
23
- class VersioningError < StandardError; end
17
+ module VersionMethods
18
+ extend ActiveSupport::Autoload
19
+
20
+ autoload :Diff
21
+ autoload :Log
22
+ end
24
23
  end
25
24
 
26
25
  ActiveSupport.on_load :cassandra_object do
@@ -1,20 +1,25 @@
1
- require 'test_helper'
2
-
3
- class HasVersions::AttributesTest < MiniTest::Spec
4
- class VersionedObject
5
- include HasVersions::Versioned
1
+ require 'helper'
6
2
 
3
+ class HasVersions::AttributesTest < MiniTest::Unit::TestCase
4
+ class VersionedModel < TestModel
7
5
  attr_accessor :name
8
- attr_accessor :time
6
+ attr_accessor :weight
9
7
  attr_accessor :color
10
8
 
11
9
  has_versions(Class.new) do
12
10
  attribute :name
13
- attribute :time
11
+ attribute :weight
14
12
  end
15
13
  end
16
14
 
17
- def test_versioned_fields
18
- assert_equal ['name', 'time'], VersionedObject.versioned_fields
15
+ def test_class_versioned_attributes
16
+ assert_equal ['name', 'weight'], VersionedModel.versioned_attributes
17
+ end
18
+
19
+ def test_instance_versioned_attributes
20
+ record = VersionedModel.new(name: 'joe', weight: 142.0, color: 'green')
21
+ expected = {'name' => 'joe', 'weight' => '142.0'}
22
+
23
+ assert_equal expected, record.versioned_attributes
19
24
  end
20
- end
25
+ end
@@ -0,0 +1,12 @@
1
+ require 'helper'
2
+
3
+ class HasVersions::ConfigurationTest < MiniTest::Unit::TestCase
4
+ def test_configuration
5
+ configuration = HasVersions::Configuration.new do
6
+ attribute :foo
7
+ attribute :bar
8
+ end
9
+
10
+ assert_equal %w(foo bar), configuration.attributes
11
+ end
12
+ end
@@ -0,0 +1,29 @@
1
+ require 'helper'
2
+
3
+ class HasVersions::ResetTest < MiniTest::Unit::TestCase
4
+ class ResetModel < TestModel
5
+ attr_accessor :name
6
+ attr_accessor :color
7
+
8
+ has_versions(TestVersion) do
9
+ attribute :name
10
+ end
11
+
12
+ def versioning_decode_value(name, value)
13
+ "hello, #{value}"
14
+ end
15
+ end
16
+
17
+ def test_from_version
18
+ end
19
+
20
+ def test_reset
21
+ reset_model = ResetModel.new(name: "bob", color: "green")
22
+ version = TestVersion.new(snapshot: {name: "joe", color: "blue"})
23
+
24
+ reset_model.reset!(version)
25
+
26
+ assert_equal "hello, joe", reset_model.name
27
+ assert_equal "green", reset_model.color
28
+ end
29
+ end
@@ -0,0 +1,68 @@
1
+ require 'helper'
2
+
3
+ class HasVersions::VersionMethods::DiffTest < MiniTest::Unit::TestCase
4
+ class DiffModel < TestModel
5
+ attr_accessor :name
6
+ attr_accessor :color
7
+ attr_accessor :weight
8
+
9
+ has_versions(TestVersion) do
10
+ attribute :name
11
+ attribute :weight
12
+ end
13
+
14
+ def versioning_decode_value(name, value)
15
+ "decoded: #{value}"
16
+ end
17
+ end
18
+
19
+ def test_diff_with_parent
20
+ target = DiffModel.new
21
+ parent = TestVersion.new(target: target, snapshot: {name: 'foo', color: 'green', weight: '4.3'})
22
+ child = TestVersion.new(target: target, parent: parent, snapshot: {name: 'bar', color: 'orange', weight: '4.3'})
23
+
24
+ diff = child.diff
25
+
26
+ assert_equal({'name' => ['decoded: foo', 'decoded: bar']}, diff)
27
+ end
28
+
29
+ def test_diff_with_parameter
30
+ target = DiffModel.new
31
+ this_version = TestVersion.new(target: target, snapshot: {name: 'foo', color: 'green', weight: '4.3'})
32
+ other_version = TestVersion.new(target: target, snapshot: {name: 'bar', color: 'orange', weight: '4.3'})
33
+
34
+ diff = this_version.diff(other_version)
35
+
36
+ assert_equal({'name' => ['decoded: bar', 'decoded: foo']}, diff)
37
+ end
38
+
39
+ def test_diff_with_nil
40
+ target = DiffModel.new
41
+ version = TestVersion.new(target: target, snapshot: {name: 'bar', color: 'orange', weight: '4.3'})
42
+
43
+ diff = version.diff
44
+
45
+ assert_equal({'name' => [nil, 'decoded: bar'], 'weight' => [nil, 'decoded: 4.3']}, diff)
46
+ end
47
+
48
+ def test_modified_attributes
49
+ target = DiffModel.new
50
+ version = TestVersion.new(target: target, snapshot: {'name' => 'joe', 'weight' => '129'})
51
+
52
+ assert_equal version.snapshot.keys, version.modified_attributes
53
+ end
54
+
55
+ def test_different_attributes
56
+ target = DiffModel.new(name: 'decoded: sam', color: 'decoded: green', weight: 'decoded: 129')
57
+ version = TestVersion.new(target: target, snapshot: {'name' => 'joe', 'weight' => '129'})
58
+
59
+ assert_equal ['name'], version.different_attributes
60
+ end
61
+
62
+ def test_decoded_snapshot
63
+ target = DiffModel.new
64
+ version = TestVersion.new(target: target, snapshot: {name: 'foo', color: 'green', weight: '4.3'})
65
+
66
+ assert_equal({"name" => "decoded: foo", "weight" => "decoded: 4.3"}, version.decoded_snapshot)
67
+ end
68
+ end
@@ -0,0 +1,33 @@
1
+ require 'helper'
2
+
3
+ class HasVersions::VersionMethods::LogTest < MiniTest::Unit::TestCase
4
+ class LogVersion < TestVersion
5
+ include HasVersions::VersionMethods::Log
6
+ end
7
+
8
+ def test_walk
9
+ grandparent = LogVersion.new
10
+ parent = LogVersion.new parent: grandparent
11
+ child = LogVersion.new parent: parent
12
+
13
+ ancestors = []
14
+ child.log.walk do |v|
15
+ ancestors << v
16
+ end
17
+
18
+ assert_equal [child, parent, grandparent], ancestors
19
+ end
20
+
21
+ def test_all
22
+ grandparent = LogVersion.new
23
+ parent = LogVersion.new parent: grandparent
24
+ child = LogVersion.new parent: parent
25
+
26
+ assert_equal [child, parent, grandparent], child.log.all
27
+ assert_equal [child, parent, grandparent], child.log.to_a
28
+ end
29
+
30
+ def test_is_enumerable
31
+ assert LogVersion.new.log.respond_to?(:collect)
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ require 'helper'
2
+
3
+ class HasVersions::VersionedTest < MiniTest::Unit::TestCase
4
+ def test_versioned_attribute
5
+ versioned_model = Class.new(TestModel) do
6
+ versioned_attribute 'hello'
7
+ end
8
+
9
+ assert_equal ['hello'], versioned_model.versioned_attributes
10
+ end
11
+
12
+ def test_to_version
13
+ record = Class.new(TestModel) do
14
+ attr_accessor :name
15
+
16
+ has_versions(TestVersion) do
17
+ attribute :name
18
+ end
19
+ end.new(name: 'wee')
20
+
21
+ version = record.to_version
22
+
23
+ assert_kind_of TestVersion, version
24
+ assert_equal record, version.target
25
+ assert_equal record.versioned_attributes, version.snapshot
26
+ end
27
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/setup'
2
+ Bundler.require
3
+
4
+ require 'minitest/autorun'
5
+ require 'support/test_version'
6
+ require 'support/test_model'
@@ -0,0 +1,21 @@
1
+ class TestModel
2
+ include HasVersions::Versioned
3
+
4
+ def initialize(attributes = {})
5
+ attributes.each do |key, value|
6
+ send("#{key}=", value)
7
+ end
8
+ end
9
+
10
+ def versioning_encode_value(name, value)
11
+ value.to_s
12
+ end
13
+
14
+ def versioning_decode_value(name, value)
15
+ value
16
+ end
17
+
18
+ def versioning_codable?(name)
19
+ true
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ class TestVersion
2
+ attr_reader :snapshot
3
+ attr_accessor :parent
4
+ attr_accessor :target
5
+
6
+ def initialize(attributes = {})
7
+ attributes.each do |key, value|
8
+ send("#{key}=", value)
9
+ end
10
+ end
11
+
12
+ def snapshot=(hash)
13
+ @snapshot = hash.stringify_keys
14
+ end
15
+ end