has_versions 0.4.9 → 0.5.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.
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