has_versions 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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