has_versions 0.3.0 → 0.4.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 (42) hide show
  1. data/.gitignore +1 -37
  2. data/Gemfile.lock +17 -45
  3. data/Rakefile +16 -16
  4. data/has_versions.gemspec +6 -6
  5. data/lib/has_versions/apply/simple.rb +1 -1
  6. data/lib/has_versions/attributes.rb +2 -26
  7. data/lib/has_versions/configuration.rb +3 -16
  8. data/lib/has_versions/diff/simple.rb +1 -1
  9. data/lib/has_versions/merge/always_conflicted.rb +9 -0
  10. data/lib/has_versions/merge/base.rb +22 -0
  11. data/lib/has_versions/merge/choose_first.rb +9 -0
  12. data/lib/has_versions/merge/diff3.rb +66 -0
  13. data/lib/has_versions/merge/fast_forward.rb +34 -0
  14. data/lib/has_versions/merge/merge_base.rb +75 -0
  15. data/lib/has_versions/merge/octopus.rb +42 -0
  16. data/lib/has_versions/merge/three_way.rb +53 -0
  17. data/lib/has_versions/merge.rb +16 -45
  18. data/lib/has_versions/orm/cassandra_object.rb +15 -0
  19. data/lib/has_versions/reset/simple.rb +2 -2
  20. data/lib/has_versions/version.rb +1 -1
  21. data/lib/has_versions/versioned.rb +1 -5
  22. data/lib/has_versions/versioning_key.rb +0 -1
  23. data/lib/has_versions.rb +10 -0
  24. data/spec/has_versions/apply_spec.rb +5 -5
  25. data/spec/has_versions/configuration_spec.rb +7 -7
  26. data/spec/has_versions/diff_spec.rb +4 -4
  27. data/spec/has_versions/merge/diff3_spec.rb +29 -0
  28. data/spec/has_versions/merge/merge_base_spec.rb +61 -0
  29. data/spec/has_versions/merge/octopus_spec.rb +74 -0
  30. data/spec/has_versions/merge/three_way_spec.rb +57 -0
  31. data/spec/has_versions/reset_spec.rb +1 -2
  32. data/spec/has_versions/stage_spec.rb +14 -15
  33. data/spec/has_versions/versioned_spec.rb +4 -4
  34. data/spec/has_versions/versioning_key_spec.rb +1 -1
  35. data/spec/spec_helper.rb +7 -8
  36. data/spec/support/matchers/be_a_uuid.rb +0 -1
  37. data/spec/support/version.rb +10 -0
  38. metadata +34 -69
  39. data/lib/has_versions/merge/stupid.rb +0 -44
  40. data/lib/has_versions/stage.rb +0 -121
  41. data/spec/has_versions/merge_spec.rb +0 -67
  42. data/spec/support/matchers/have_key.rb +0 -25
data/.gitignore CHANGED
@@ -1,42 +1,6 @@
1
- # simplecov generated
2
1
  coverage
3
-
4
- # rdoc generated
5
2
  rdoc
6
-
7
- # yard generated
8
3
  doc
9
4
  .yardoc
10
-
11
- # bundler
12
5
  .bundle
13
-
14
- # jeweler generated
15
- pkg
16
-
17
- # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
18
- #
19
- # * Create a file at ~/.gitignore
20
- # * Include files you want ignored
21
- # * Run: git config --global core.excludesfile ~/.gitignore
22
- #
23
- # After doing this, these files will be ignored in all your git projects,
24
- # saving you from having to 'pollute' every project you touch with them
25
- #
26
- # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
27
- #
28
- # For MacOS:
29
- #
30
- #.DS_Store
31
- #
32
- # For TextMate
33
- #*.tmproj
34
- #tmtags
35
- #
36
- # For emacs:
37
- #*~
38
- #\#*
39
- #.\#*
40
- #
41
- # For vim:
42
- #*.swp
6
+ Gemfile.lock
data/Gemfile.lock CHANGED
@@ -1,63 +1,35 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- has_versions (0.3.0)
5
- activesupport (~> 3)
4
+ has_versions (0.4.0)
5
+ activesupport (~> 3.0)
6
6
  i18n
7
7
  simple_uuid
8
8
 
9
9
  GEM
10
10
  remote: http://rubygems.org/
11
11
  specs:
12
- activesupport (3.0.5)
13
- builder (3.0.0)
14
- cucumber (0.10.0)
15
- builder (>= 2.1.2)
12
+ activesupport (3.1.0)
13
+ multi_json (~> 1.0)
14
+ diff-lcs (1.1.3)
15
+ i18n (0.6.0)
16
+ multi_json (1.0.3)
17
+ rspec (2.6.0)
18
+ rspec-core (~> 2.6.0)
19
+ rspec-expectations (~> 2.6.0)
20
+ rspec-mocks (~> 2.6.0)
21
+ rspec-core (2.6.4)
22
+ rspec-expectations (2.6.0)
16
23
  diff-lcs (~> 1.1.2)
17
- gherkin (~> 2.3.2)
18
- json (~> 1.4.6)
19
- term-ansicolor (~> 1.0.5)
20
- diff-lcs (1.1.2)
21
- gherkin (2.3.4)
22
- json (~> 1.4.6)
23
- i18n (0.5.0)
24
- json (1.4.6)
25
- reek (1.2.8)
26
- ruby2ruby (~> 1.2)
27
- ruby_parser (~> 2.0)
28
- sexp_processor (~> 3.0)
29
- roodi (2.1.0)
30
- ruby_parser
31
- rspec (2.5.0)
32
- rspec-core (~> 2.5.0)
33
- rspec-expectations (~> 2.5.0)
34
- rspec-mocks (~> 2.5.0)
35
- rspec-core (2.5.1)
36
- rspec-expectations (2.5.0)
37
- diff-lcs (~> 1.1.2)
38
- rspec-mocks (2.5.0)
39
- ruby2ruby (1.2.5)
40
- ruby_parser (~> 2.0)
41
- sexp_processor (~> 3.0)
42
- ruby_parser (2.0.6)
43
- sexp_processor (~> 3.0)
44
- sexp_processor (3.0.5)
45
- simple_uuid (0.1.1)
46
- simplecov (0.4.1)
47
- simplecov-html (~> 0.4.3)
48
- simplecov-html (0.4.3)
49
- term-ansicolor (1.0.5)
50
- yard (0.6.5)
24
+ rspec-mocks (2.6.0)
25
+ simple_uuid (0.2.0)
26
+ yard (0.6.8)
51
27
 
52
28
  PLATFORMS
53
29
  ruby
54
30
 
55
31
  DEPENDENCIES
56
32
  bundler (~> 1.0.0)
57
- cucumber
58
33
  has_versions!
59
- reek (~> 1.2.8)
60
- roodi (~> 2.1.0)
61
- rspec (~> 2)
62
- simplecov (>= 0.3.8)
34
+ rspec (~> 2.0)
63
35
  yard (~> 0.6.0)
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- require 'bundler'
1
+ require 'bundler/setup'
2
2
  Bundler::GemHelper.install_tasks
3
3
 
4
4
  require 'rspec/core'
@@ -7,23 +7,23 @@ RSpec::Core::RakeTask.new(:spec) do |spec|
7
7
  spec.pattern = FileList['spec/**/*_spec.rb']
8
8
  end
9
9
 
10
- require 'cucumber/rake/task'
11
- Cucumber::Rake::Task.new(:features)
10
+ # require 'cucumber/rake/task'
11
+ # Cucumber::Rake::Task.new(:features)
12
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
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
19
19
 
20
- require 'roodi'
21
- require 'roodi_task'
22
- RoodiTask.new do |t|
23
- t.verbose = false
24
- end
20
+ # require 'roodi'
21
+ # require 'roodi_task'
22
+ # RoodiTask.new do |t|
23
+ # t.verbose = false
24
+ # end
25
25
 
26
26
  task :default => :spec
27
27
 
28
- require 'yard'
29
- YARD::Rake::YardocTask.new
28
+ # require 'yard'
29
+ # YARD::Rake::YardocTask.new
data/has_versions.gemspec CHANGED
@@ -27,14 +27,14 @@ Gem::Specification.new do |s|
27
27
  s.licenses = ["MIT"]
28
28
 
29
29
  s.add_runtime_dependency("i18n", [">= 0"])
30
- s.add_runtime_dependency("activesupport", ["~> 3"])
30
+ s.add_runtime_dependency("activesupport", ["~> 3.0"])
31
31
  s.add_runtime_dependency("simple_uuid", [">= 0"])
32
- s.add_development_dependency("rspec", ["~> 2"])
32
+ s.add_development_dependency("rspec", ["~> 2.0"])
33
33
  s.add_development_dependency("yard", ["~> 0.6.0"])
34
- s.add_development_dependency("cucumber", [">= 0"])
35
34
  s.add_development_dependency("bundler", ["~> 1.0.0"])
36
- s.add_development_dependency("simplecov", [">= 0.3.8"])
37
- s.add_development_dependency("reek", ["~> 1.2.8"])
38
- s.add_development_dependency("roodi", ["~> 2.1.0"])
35
+ # s.add_development_dependency("cucumber", [">= 0"])
36
+ # s.add_development_dependency("simplecov", [">= 0.3.8"])
37
+ # s.add_development_dependency("reek", ["~> 1.2.8"])
38
+ # s.add_development_dependency("roodi", ["~> 2.1.0"])
39
39
  end
40
40
 
@@ -14,7 +14,7 @@ module HasVersions
14
14
  module Simple
15
15
  def apply(*patches)
16
16
  self.class.new.tap do |version| #TODO is new the right thing here? it doe scall initialize (allocate does not)
17
- ours = snapshot.with_indifferent_access #TEST is it necessary to deep dup the snapshot?
17
+ ours = snapshot.dup #TEST is it necessary to deep dup the snapshot?
18
18
 
19
19
  patches.each do |patch|
20
20
  patch.each do |key, (a, b)|
@@ -1,34 +1,10 @@
1
1
  module HasVersions
2
2
  module Attributes
3
-
4
3
  def versioned_attributes
5
- versioning_configuration.attributes.inject(HashWithIndifferentAccess.new) do |memo, (key, options)|
6
-
7
- memo[key] = versioning_encode_value(__send__(key), options)
4
+ versioning_configuration.attributes.inject({}) do |memo, attribute|
5
+ memo[attribute] = versioning_encode_value(attribute, send(attribute))
8
6
  memo
9
7
  end
10
8
  end
11
-
12
- private
13
-
14
- def versioning_decode_value(value, options)
15
- return value if value.nil?
16
-
17
- if options[:expected] && !value.kind_of?(options[:expected]) && options[:decoder]
18
- options[:decoder].call(value)
19
- else
20
- value
21
- end
22
- end
23
-
24
- def versioning_encode_value(value, options)
25
- return value if value.nil?
26
-
27
- if options[:encoder]
28
- options[:encoder].call(value)
29
- else
30
- value
31
- end
32
- end
33
9
  end
34
10
  end
@@ -2,27 +2,14 @@ module HasVersions
2
2
 
3
3
  class Configuration
4
4
  attr_accessor :attributes
5
- attr_accessor :types
6
-
7
- DEFAULT_TYPES = {
8
- set: { expected: Set, decoder: ->(value) { Set.new(value) } },
9
- time_with_zone: { expected: ActiveSupport::TimeWithZone, encoder: ->(value) { value.utc.xmlschema(6) }, decoder: ->(value) { Time.xmlschema(value).in_time_zone } }
10
- }.freeze
11
5
 
12
6
  def initialize(&block)
13
- @attributes = {}.with_indifferent_access
14
- @types = DEFAULT_TYPES.with_indifferent_access
7
+ self.attributes = []
15
8
  instance_eval(&block)
16
9
  end
17
10
 
18
- def type(name, options={})
19
- @types[name] = options.with_indifferent_access
20
- end
21
-
22
- def attribute(name, options={})
23
- options.merge!(@types[options[:type]]) if @types[options[:type]]
24
- @attributes[name] = options.with_indifferent_access
11
+ def attribute(name)
12
+ attributes << name.to_s
25
13
  end
26
14
  end
27
-
28
15
  end
@@ -1,7 +1,7 @@
1
1
  module HasVersions
2
2
  module Diff
3
3
  # takes a version and returns a diff (patch) from self
4
- # version must respond to #snapshot with an attributes hash
4
+ # version must respond to #snapshot with an attributes hash (or something that responds to [] and keys)
5
5
  # diff format is:
6
6
  # {
7
7
  # attribute_name: [a, b]
@@ -0,0 +1,9 @@
1
+ module HasVersions
2
+ module Merge
3
+ class AlwaysConflicted < Base
4
+ def conflicted?
5
+ true
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,22 @@
1
+ module HasVersions
2
+ module Merge
3
+ class Base
4
+ attr_accessor :versions, :options
5
+ attr_accessor :resolution, :conflicts
6
+
7
+ def initialize(versions, options={})
8
+ @versions = versions
9
+ @options = options
10
+ @conflicts = {}.with_indifferent_access
11
+ end
12
+
13
+ def merge
14
+ # implemented by subclasses
15
+ end
16
+
17
+ def conflicted?
18
+ !self.conflicts.empty?
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ module HasVersions
2
+ module Merge
3
+ class ChooseFirst < Base
4
+ def merge
5
+ self.resolution = versions.first
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,66 @@
1
+ module HasVersions
2
+ module Merge
3
+ module Diff3
4
+
5
+ # 3-way merge, extended to support more than one other
6
+ # base ours *theirs.uniq take
7
+ # A A [A] A (ours)
8
+ # A B [A] B (ours)
9
+ # A A [B] B (theirs)
10
+ # B A [A] A (ours)
11
+ # B A [A,B] conflict
12
+ # B A [C] conflict
13
+ #
14
+ # cases where values are missing:
15
+ # m A A A
16
+ # m B A conflict
17
+ # A m A A
18
+ # A m B B
19
+ # A A m A
20
+ # A B m B
21
+ # m m A A
22
+ # m A m A
23
+ #
24
+ # returns an array [clean, result]
25
+ # where clean is a boolean
26
+ # and result is an array in the conflicts case, or a single value in the clean case
27
+
28
+ def diff3(base, ours, *theirs)
29
+ theirs = theirs.uniq
30
+
31
+ # if there is more than one possible value, it is already a conflict
32
+ if theirs.size > 1
33
+ # add ours to conflicts if it is different from base
34
+ if ours != base && !theirs.include?(ours)
35
+ theirs << ours
36
+ end
37
+ return [false, theirs]
38
+ end
39
+
40
+ theirs = theirs.first
41
+
42
+ if ours == base && base == theirs
43
+ [true, ours]
44
+ elsif base == theirs
45
+ [true, ours]
46
+ elsif ours == base
47
+ [true, theirs]
48
+ elsif ours == theirs
49
+ [true, ours]
50
+ elsif ours == :_missing
51
+ [true, theirs]
52
+ elsif theirs == :_missing
53
+ [true, ours]
54
+ else
55
+ [false, [ours, theirs]]
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def value_or_missing(snapshot, key)
62
+ snapshot.keys.include?(key) ? snapshot[key] : :_missing
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,34 @@
1
+ module HasVersions
2
+ module Merge
3
+ class FastForward < Base
4
+ # Takes exactly two versions and resolves the merge using ancestry.
5
+ # One of the two versions must be an ancestor of the other.
6
+ #
7
+ # expects versions to define contains? which returns true if the given version
8
+ # is an ancestor of the receiver
9
+ # eg if v1 is an ancestor of v2, then
10
+ # v2.contains?(v1) #=> true
11
+ #
12
+ # raises MergeFailed if anything but two versions are given, or if neither version
13
+ # is an ancestor of the other.
14
+
15
+ def initialize(versions, options={})
16
+ super
17
+ if versions.size != 2
18
+ raise HasVersions::MergeFailed, "Cannot fast forward merge with #{versions.size} versions"
19
+ end
20
+ end
21
+
22
+ def merge
23
+ v1, v2 = versions
24
+ if v1.contains?(v2)
25
+ self.resolution = v1
26
+ elsif v2.contains?(v1)
27
+ self.resolution = v2
28
+ else
29
+ raise HasVersions::MergeFailed, "cannot fast forward if neither version is an ancestor"
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,75 @@
1
+ module HasVersions
2
+ module Merge
3
+ module MergeBase
4
+ # Finds optimal merge bases for any number of versions
5
+ # Essentially a copy of git's algorithm
6
+ # Expects versions to respond to parents with an array of parent versions
7
+ def merge_bases(versions)
8
+ versions = versions.dup
9
+ one = versions.shift
10
+ twos = versions
11
+
12
+ bases = determine_merge_bases(one, twos)
13
+ if twos.include?(one)
14
+ return bases
15
+ end
16
+
17
+ if bases.size == 1
18
+ return bases
19
+ end
20
+
21
+ bases.each_with_index do |base1, i|
22
+ next if base1 == bases.last
23
+
24
+ bases.each_with_index do |base2, j|
25
+ next if base1.nil? || base2.nil?
26
+ sub_bases = determine_merge_bases(base1, [base2])
27
+ sub_bases.each do |sub_base|
28
+ bases[i] = nil if sub_base == base1
29
+ bases[j] = nil if sub_base == base2
30
+ end
31
+ end
32
+ end
33
+
34
+ bases.compact
35
+ end
36
+
37
+ private
38
+
39
+ def determine_merge_bases(one, twos)
40
+ stale = Set.new
41
+ parent1 = Set.new
42
+ parent2 = Set.new
43
+ result = Set.new
44
+
45
+ interesting = []
46
+
47
+ if twos.include?(one)
48
+ return [one]
49
+ end
50
+
51
+ parent1 << one
52
+ parent2 += twos
53
+
54
+ interesting << one
55
+ interesting += twos
56
+
57
+ while !(interesting - stale.to_a).empty?
58
+ candidate = interesting.shift
59
+ if parent1.include?(candidate) && parent2.include?(candidate) && !stale.include?(candidate)
60
+ result << candidate
61
+ end
62
+
63
+ candidate.parents.each do |parent|
64
+ stale << parent if stale.include?(candidate)
65
+ parent1 << parent if parent1.include?(candidate)
66
+ parent2 << parent if parent2.include?(candidate)
67
+ interesting << parent
68
+ end
69
+ end
70
+
71
+ result.to_a.reject { |r| stale.include?(r) }
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,42 @@
1
+ module HasVersions
2
+ module Merge
3
+ # Merge >2 versions
4
+ # Works by doing a 3-way merge for first 2 versions, then merging the result with
5
+ # the next version for each version given.
6
+ # eg for 4 versions there are three merges: v1+v2, then (v1+v2)+v3, then ((v1+v2)+v3)+v4
7
+ # conflicts will be an accumulation of all conflicting values from each merge
8
+ class Octopus < Base
9
+ def initialize(versions, options={})
10
+ super
11
+ if versions.size <= 2
12
+ raise HasVersions::MergeFailed, "Cannot octopus merge with #{versions.size} versions, expect >2"
13
+ end
14
+ end
15
+
16
+ def merge
17
+ self.resolution = versions.inject(resolution) do |res, version|
18
+ if res
19
+ merge = ThreeWay.new([res, version], options)
20
+ merge.merge
21
+ add_conflicts(merge.conflicts)
22
+ res = merge.resolution
23
+ else
24
+ res = version
25
+ end
26
+ res
27
+ end
28
+ resolution.parents = versions
29
+ resolution
30
+ end
31
+
32
+ private
33
+ def add_conflicts(conflicts)
34
+ conflicts.each do |attribute, values|
35
+ self.conflicts[attribute] ||= []
36
+ self.conflicts[attribute] += values
37
+ self.conflicts[attribute].uniq!
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,53 @@
1
+ module HasVersions
2
+ module Merge
3
+ # Merges two versions using ancestry and 3-way diff
4
+ # expects versions to respond to parents= to set parents
5
+ # does not check ancestry when setting parents - use FastForward if one version
6
+ # is an ancestor of another or they are identical
7
+ class ThreeWay < Base
8
+ include MergeBase
9
+ include Diff3
10
+
11
+ def initialize(versions, options={})
12
+ super
13
+ if versions.size != 2
14
+ raise HasVersions::MergeFailed, "Cannot 3-way merge with #{versions.size} versions, expect 2"
15
+ end
16
+ end
17
+
18
+ # assume the first version is ours
19
+ def merge
20
+ version_class = options[:version_class] || versions.first.class
21
+ # find merge base or bases
22
+ bases = merge_bases(versions)
23
+ # raise if there is more than one base
24
+ # TODO could potentially just choose one (that's what git does)
25
+ raise MergeFailed, "More than one merge base" if bases.size > 1
26
+
27
+ base = bases.first.try(:snapshot) || {}.with_indifferent_access
28
+ ours = versions.first.snapshot
29
+ theirs = versions.last.snapshot
30
+
31
+ self.resolution = version_class.new
32
+ self.resolution.parents = versions
33
+
34
+ # get the full list of attributes in each version and the merge base
35
+ attributes = (versions.collect { |v| v.snapshot.keys }.flatten + base.keys).uniq
36
+
37
+ # do 3-way merge on each attribute
38
+ attributes.each do |key|
39
+ clean, result = diff3(value_or_missing(base, key), value_or_missing(ours, key), value_or_missing(theirs, key))
40
+ if clean
41
+ resolution.snapshot[key] = result
42
+ else
43
+ resolution.snapshot[key] = ours[key]
44
+ conflicts[key] = result
45
+ end
46
+ end
47
+
48
+ resolution
49
+ end
50
+ end
51
+ end
52
+ end
53
+
@@ -1,6 +1,8 @@
1
1
  module HasVersions
2
2
 
3
- class MergeConflict < VersioningError
3
+ class MergeFailed < VersioningError; end
4
+
5
+ class MergeConflict < MergeFailed
4
6
  attr_accessor :conflicts
5
7
  attr_accessor :result
6
8
 
@@ -13,49 +15,18 @@ module HasVersions
13
15
  module Merge
14
16
  extend ActiveSupport::Autoload
15
17
 
16
- autoload :Stupid
17
-
18
- module Diff3
19
-
20
- # 3-way merge, extended to support more than one other
21
- # base ours *theirs.uniq take
22
- # A A [A] A (ours)
23
- # A B [A] B (ours)
24
- # A A [B] B (theirs)
25
- # B A [A] A (ours)
26
- # B A [A,B] conflict
27
- # B A [C] conflict
28
- #
29
- # returns an array [clean, result]
30
- # where clean is a boolean
31
- # and result is an array in the conflicts case, or a single value in the clean case
32
-
33
- def diff3(base, ours, *theirs)
34
- theirs = theirs.uniq
35
-
36
- # if there is more than one possible value, it is already a conflict
37
- if theirs.size > 1
38
- # add ours to conflicts if it is different from base
39
- if ours != base && !theirs.include?(ours)
40
- theirs << ours
41
- end
42
- return [false, theirs]
43
- end
44
-
45
- theirs = theirs.first
46
-
47
- if ours == base && base == theirs
48
- [true, ours]
49
- elsif base == theirs
50
- [true, ours]
51
- elsif ours == base
52
- [true, theirs]
53
- elsif ours == theirs
54
- [true, ours]
55
- else
56
- [false, [ours, theirs]]
57
- end
58
- end
59
- end
18
+ autoload :Base
19
+
20
+ autoload :FastForward
21
+ autoload :ThreeWay
22
+ autoload :Octopus
23
+
24
+ # strategies for testing
25
+ autoload :ChooseFirst
26
+ autoload :AlwaysConflicted
27
+
28
+ autoload :Diff3
29
+ autoload :MergeBase
30
+
60
31
  end
61
32
  end
@@ -0,0 +1,15 @@
1
+ module HasVersions
2
+ module Orm
3
+ module CassandraObject
4
+ def versioning_encode_value(name, value)
5
+ return if value.nil?
6
+ attribute_definitions[name.to_sym].coder.encode(value)
7
+ end
8
+
9
+ def versioning_decode_value(name, value)
10
+ return if value.nil?
11
+ attribute_definitions[name.to_sym].coder.decode(value)
12
+ end
13
+ end
14
+ end
15
+ end