activerecord-temporal 0.1.0 → 0.2.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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/README.md +775 -7
  4. data/lib/activerecord/temporal/application_versioning/application_versioned.rb +122 -0
  5. data/lib/activerecord/temporal/application_versioning/command_recorder.rb +14 -0
  6. data/lib/activerecord/temporal/application_versioning/migration.rb +25 -0
  7. data/lib/activerecord/temporal/application_versioning/schema_statements.rb +33 -0
  8. data/lib/activerecord/temporal/application_versioning.rb +3 -69
  9. data/lib/activerecord/temporal/patches/association_reflection.rb +10 -3
  10. data/lib/activerecord/temporal/patches/command_recorder.rb +23 -0
  11. data/lib/activerecord/temporal/patches/join_dependency.rb +3 -0
  12. data/lib/activerecord/temporal/patches/merger.rb +1 -1
  13. data/lib/activerecord/temporal/patches/relation.rb +10 -6
  14. data/lib/activerecord/temporal/patches/through_association.rb +4 -1
  15. data/lib/activerecord/temporal/{as_of_query → querying}/association_macros.rb +1 -1
  16. data/lib/activerecord/temporal/querying/association_scope.rb +55 -0
  17. data/lib/activerecord/temporal/{as_of_query → querying}/association_walker.rb +1 -1
  18. data/lib/activerecord/temporal/querying/predicate_builder/contains_handler.rb +24 -0
  19. data/lib/activerecord/temporal/querying/predicate_builder/handlers.rb +31 -0
  20. data/lib/activerecord/temporal/querying/query_methods.rb +37 -0
  21. data/lib/activerecord/temporal/querying/scope_registry.rb +95 -0
  22. data/lib/activerecord/temporal/querying/scoping.rb +70 -0
  23. data/lib/activerecord/temporal/{as_of_query → querying}/time_dimensions.rb +13 -3
  24. data/lib/activerecord/temporal/querying/where_clause_refinement.rb +17 -0
  25. data/lib/activerecord/temporal/querying.rb +95 -0
  26. data/lib/activerecord/temporal/scoping.rb +7 -0
  27. data/lib/activerecord/temporal/system_versioning/command_recorder.rb +27 -1
  28. data/lib/activerecord/temporal/system_versioning/history_model.rb +47 -0
  29. data/lib/activerecord/temporal/system_versioning/history_model_namespace.rb +45 -0
  30. data/lib/activerecord/temporal/system_versioning/history_models.rb +29 -0
  31. data/lib/activerecord/temporal/system_versioning/migration.rb +35 -0
  32. data/lib/activerecord/temporal/system_versioning/schema_creation.rb +2 -2
  33. data/lib/activerecord/temporal/system_versioning/schema_statements.rb +80 -8
  34. data/lib/activerecord/temporal/system_versioning/system_versioned.rb +13 -0
  35. data/lib/activerecord/temporal/system_versioning.rb +6 -18
  36. data/lib/activerecord/temporal/version.rb +1 -1
  37. data/lib/activerecord/temporal.rb +75 -30
  38. metadata +27 -14
  39. data/lib/activerecord/temporal/as_of_query/association_scope.rb +0 -54
  40. data/lib/activerecord/temporal/as_of_query/query_methods.rb +0 -24
  41. data/lib/activerecord/temporal/as_of_query/scope_registry.rb +0 -38
  42. data/lib/activerecord/temporal/as_of_query.rb +0 -109
  43. data/lib/activerecord/temporal/system_versioning/model.rb +0 -37
  44. data/lib/activerecord/temporal/system_versioning/namespace.rb +0 -34
@@ -1,63 +1,108 @@
1
1
  require "active_support"
2
2
 
3
- require_relative "temporal/application_versioning"
4
- require_relative "temporal/as_of_query"
5
- require_relative "temporal/as_of_query/association_macros"
6
- require_relative "temporal/as_of_query/association_scope"
7
- require_relative "temporal/as_of_query/association_walker"
8
- require_relative "temporal/as_of_query/query_methods"
9
- require_relative "temporal/as_of_query/scope_registry"
10
- require_relative "temporal/as_of_query/time_dimensions"
3
+ require_relative "temporal/application_versioning/application_versioned"
4
+ require_relative "temporal/application_versioning/command_recorder"
5
+ require_relative "temporal/application_versioning/migration"
6
+ require_relative "temporal/application_versioning/schema_statements"
7
+ require_relative "temporal/querying/association_macros"
8
+ require_relative "temporal/querying/association_scope"
9
+ require_relative "temporal/querying/association_walker"
10
+ require_relative "temporal/querying/predicate_builder/handlers"
11
+ require_relative "temporal/querying/query_methods"
12
+ require_relative "temporal/querying/scope_registry"
13
+ require_relative "temporal/querying/scoping"
14
+ require_relative "temporal/querying/time_dimensions"
11
15
  require_relative "temporal/patches/association_reflection"
16
+ require_relative "temporal/patches/command_recorder"
12
17
  require_relative "temporal/patches/join_dependency"
13
18
  require_relative "temporal/patches/merger"
14
19
  require_relative "temporal/patches/relation"
15
20
  require_relative "temporal/patches/through_association"
16
- require_relative "temporal/system_versioning"
17
21
  require_relative "temporal/system_versioning/command_recorder"
18
- require_relative "temporal/system_versioning/namespace"
19
- require_relative "temporal/system_versioning/model"
22
+ require_relative "temporal/system_versioning/history_model_namespace"
23
+ require_relative "temporal/system_versioning/history_model"
24
+ require_relative "temporal/system_versioning/history_models"
25
+ require_relative "temporal/system_versioning/migration"
20
26
  require_relative "temporal/system_versioning/schema_creation"
21
27
  require_relative "temporal/system_versioning/schema_definitions"
22
28
  require_relative "temporal/system_versioning/schema_statements"
29
+ require_relative "temporal/system_versioning/system_versioned"
30
+ require_relative "temporal/application_versioning"
31
+ require_relative "temporal/querying"
32
+ require_relative "temporal/scoping"
33
+ require_relative "temporal/system_versioning"
34
+
35
+ module ActiveRecord::Temporal
36
+ def system_versioning
37
+ include SystemVersioning
38
+ end
39
+
40
+ def application_versioning(**options)
41
+ include Querying
42
+ include ApplicationVersioning
43
+
44
+ self.time_dimensions = options[:dimensions] if options[:dimensions]
45
+ end
46
+ end
23
47
 
24
48
  ActiveSupport.on_load(:active_record) do
25
49
  require "active_record/connection_adapters/postgresql_adapter" # TODO: add test
26
50
 
27
- ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.include(ActiveRecord::Temporal::SystemVersioning::SchemaStatements)
28
- ActiveRecord::Migration::CommandRecorder.include(ActiveRecord::Temporal::SystemVersioning::CommandRecorder)
29
- ActiveRecord::Relation.include(ActiveRecord::Temporal::AsOfQuery::QueryMethods)
51
+ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
52
+ .include ActiveRecord::Temporal::ApplicationVersioning::SchemaStatements
53
+
54
+ ActiveRecord::Migration::CommandRecorder
55
+ .include ActiveRecord::Temporal::ApplicationVersioning::CommandRecorder
56
+
57
+ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
58
+ .include ActiveRecord::Temporal::SystemVersioning::SchemaStatements
59
+
60
+ ActiveRecord::Migration::CommandRecorder
61
+ .include ActiveRecord::Temporal::SystemVersioning::CommandRecorder
62
+
63
+ ActiveRecord::Relation
64
+ .include ActiveRecord::Temporal::Querying::QueryMethods
30
65
 
31
66
  # Patches
32
67
 
33
- # Patches the `build_arel` method wrap itself in the as-of query scope registry.
68
+ # Patches `#invert_drop` to remove the `system_versioning` option. The original
69
+ # method determines reversibility by looking for the presence of arguments
70
+ ActiveRecord::Migration::CommandRecorder
71
+ .prepend ActiveRecord::Temporal::Patches::CommandRecorder
72
+
73
+ # Patches `#build_arel` to wrap itself in the as-of query scope registry.
34
74
  # This is what allows temporal association scopes to be aware of the time-scope
35
75
  # value of the relation that included them.
36
76
  #
37
- # Patches the `instantiate_records` method to call `initialize_time_scope_from_relation`
77
+ # Patches `#instantiate_records` method to call `initialize_time_tags_from_relation`
38
78
  # on each loaded record.
39
- ActiveRecord::Relation.prepend(ActiveRecord::Temporal::Patches::Relation)
79
+ ActiveRecord::Relation
80
+ .prepend ActiveRecord::Temporal::Patches::Relation
40
81
 
41
- # Patches the `merge` method (called by `Relation#merge`) to handle the new
42
- # query method `time_scope` that this gem adds.
43
- ActiveRecord::Relation::Merger.prepend(ActiveRecord::Temporal::Patches::Merger)
82
+ # Patches `#merge` (called by `Relation#merge`) to handle the new query method
83
+ # `time_tags` that this gem adds.
84
+ ActiveRecord::Relation::Merger
85
+ .prepend ActiveRecord::Temporal::Patches::Merger
44
86
 
45
- # Patches the preloader's `through_scope` method to pass along the relation's
46
- # time-scope values when it handles has-many-through associations. The handler
47
- # for has-many assoication uses `Relation#merge`, but this one doesn't.
48
- ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(ActiveRecord::Temporal::Patches::ThroughAssociation)
87
+ # Patches `#through_scope` to pass along the relation's time tag values when it
88
+ # handles has-many-through associations. The handler for has-many association
89
+ # uses `Relation#merge`, but this one doesn't.
90
+ ActiveRecord::Associations::Preloader::ThroughAssociation
91
+ .prepend ActiveRecord::Temporal::Patches::ThroughAssociation
49
92
 
50
93
  # This permits association scopes generated by this gem to be eager-load if they
51
- # are "optionally instance-dependent." That is to say, they accept arguments,
52
- # but don't require any arguments.
94
+ # are "optionally instance-dependent." That is to say, they accept but don't
95
+ # require arguments.
53
96
  #
54
- # I think permitting eager-loading optionally instance-dependent association
55
- # scopes would make sense as a general feature. See this PR for my justification:
97
+ # I think permitting eager-loading of such scopes would make sense as a
98
+ # standalone feature for Active Record. See this PR for my justification:
56
99
  # https://github.com/rails/rails/pull/56004
57
- ActiveRecord::Reflection::AssociationReflection.prepend(ActiveRecord::Temporal::Patches::AssociationReflection)
100
+ ActiveRecord::Reflection::AssociationReflection
101
+ .prepend ActiveRecord::Temporal::Patches::AssociationReflection
58
102
 
59
103
  # This is a copy of a fix from https://github.com/rails/rails/pull/56088 that
60
104
  # impacts this gem. I has been backported to supported stable versions of
61
105
  # Active Record, but until those patches are released it's included here.
62
- ActiveRecord::Associations::JoinDependency.prepend(ActiveRecord::Temporal::Patches::JoinDependency)
106
+ ActiveRecord::Associations::JoinDependency
107
+ .prepend ActiveRecord::Temporal::Patches::JoinDependency
63
108
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-temporal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin-Alexander
@@ -15,7 +15,7 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '7.2'
18
+ version: '8'
19
19
  - - "<"
20
20
  - !ruby/object:Gem::Version
21
21
  version: '9.0'
@@ -25,7 +25,7 @@ dependencies:
25
25
  requirements:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
- version: '7.2'
28
+ version: '8'
29
29
  - - "<"
30
30
  - !ruby/object:Gem::Version
31
31
  version: '9.0'
@@ -35,7 +35,7 @@ dependencies:
35
35
  requirements:
36
36
  - - ">="
37
37
  - !ruby/object:Gem::Version
38
- version: '7.2'
38
+ version: '8'
39
39
  - - "<"
40
40
  - !ruby/object:Gem::Version
41
41
  version: '9.0'
@@ -45,7 +45,7 @@ dependencies:
45
45
  requirements:
46
46
  - - ">="
47
47
  - !ruby/object:Gem::Version
48
- version: '7.2'
48
+ version: '8'
49
49
  - - "<"
50
50
  - !ruby/object:Gem::Version
51
51
  version: '9.0'
@@ -77,25 +77,38 @@ files:
77
77
  - README.md
78
78
  - lib/activerecord/temporal.rb
79
79
  - lib/activerecord/temporal/application_versioning.rb
80
- - lib/activerecord/temporal/as_of_query.rb
81
- - lib/activerecord/temporal/as_of_query/association_macros.rb
82
- - lib/activerecord/temporal/as_of_query/association_scope.rb
83
- - lib/activerecord/temporal/as_of_query/association_walker.rb
84
- - lib/activerecord/temporal/as_of_query/query_methods.rb
85
- - lib/activerecord/temporal/as_of_query/scope_registry.rb
86
- - lib/activerecord/temporal/as_of_query/time_dimensions.rb
80
+ - lib/activerecord/temporal/application_versioning/application_versioned.rb
81
+ - lib/activerecord/temporal/application_versioning/command_recorder.rb
82
+ - lib/activerecord/temporal/application_versioning/migration.rb
83
+ - lib/activerecord/temporal/application_versioning/schema_statements.rb
87
84
  - lib/activerecord/temporal/patches/association_reflection.rb
85
+ - lib/activerecord/temporal/patches/command_recorder.rb
88
86
  - lib/activerecord/temporal/patches/join_dependency.rb
89
87
  - lib/activerecord/temporal/patches/merger.rb
90
88
  - lib/activerecord/temporal/patches/relation.rb
91
89
  - lib/activerecord/temporal/patches/through_association.rb
90
+ - lib/activerecord/temporal/querying.rb
91
+ - lib/activerecord/temporal/querying/association_macros.rb
92
+ - lib/activerecord/temporal/querying/association_scope.rb
93
+ - lib/activerecord/temporal/querying/association_walker.rb
94
+ - lib/activerecord/temporal/querying/predicate_builder/contains_handler.rb
95
+ - lib/activerecord/temporal/querying/predicate_builder/handlers.rb
96
+ - lib/activerecord/temporal/querying/query_methods.rb
97
+ - lib/activerecord/temporal/querying/scope_registry.rb
98
+ - lib/activerecord/temporal/querying/scoping.rb
99
+ - lib/activerecord/temporal/querying/time_dimensions.rb
100
+ - lib/activerecord/temporal/querying/where_clause_refinement.rb
101
+ - lib/activerecord/temporal/scoping.rb
92
102
  - lib/activerecord/temporal/system_versioning.rb
93
103
  - lib/activerecord/temporal/system_versioning/command_recorder.rb
94
- - lib/activerecord/temporal/system_versioning/model.rb
95
- - lib/activerecord/temporal/system_versioning/namespace.rb
104
+ - lib/activerecord/temporal/system_versioning/history_model.rb
105
+ - lib/activerecord/temporal/system_versioning/history_model_namespace.rb
106
+ - lib/activerecord/temporal/system_versioning/history_models.rb
107
+ - lib/activerecord/temporal/system_versioning/migration.rb
96
108
  - lib/activerecord/temporal/system_versioning/schema_creation.rb
97
109
  - lib/activerecord/temporal/system_versioning/schema_definitions.rb
98
110
  - lib/activerecord/temporal/system_versioning/schema_statements.rb
111
+ - lib/activerecord/temporal/system_versioning/system_versioned.rb
99
112
  - lib/activerecord/temporal/version.rb
100
113
  homepage: https://github.com/Martin-Alexander/activerecord-temporal
101
114
  licenses:
@@ -1,54 +0,0 @@
1
- module ActiveRecord::Temporal
2
- module AsOfQuery
3
- class AssociationScope
4
- class << self
5
- def build(block)
6
- scope = build_scope(block || default_base_scope)
7
-
8
- def scope.as_of_scope? = true
9
-
10
- scope
11
- end
12
-
13
- private
14
-
15
- def build_scope(block)
16
- temporal_scope = build_temporal_scope
17
-
18
- if block.arity != 0
19
- return ->(owner) do
20
- base = instance_exec(owner, &block)
21
- instance_exec(owner, base, &temporal_scope)
22
- end
23
- end
24
-
25
- ->(owner = nil) do
26
- base = instance_exec(owner, &block)
27
- instance_exec(owner, base, &temporal_scope)
28
- end
29
- end
30
-
31
- def build_temporal_scope
32
- ->(owner, base) do
33
- time_scopes = ScopeRegistry.query_scope_for(time_dimensions)
34
- owner_time_scopes = owner&.time_scopes_for(time_dimensions)
35
-
36
- time_scopes.merge!(owner_time_scopes) if owner_time_scopes
37
-
38
- default_time_scopes = time_dimensions.map do |dimension|
39
- [dimension, Time.current]
40
- end.to_h
41
-
42
- time_scope_constraints = default_time_scopes.merge(time_scopes)
43
-
44
- base.existed_at(time_scope_constraints).time_scope(time_scopes)
45
- end
46
- end
47
-
48
- def default_base_scope
49
- proc { all }
50
- end
51
- end
52
- end
53
- end
54
- end
@@ -1,24 +0,0 @@
1
- module ActiveRecord::Temporal
2
- module AsOfQuery
3
- module QueryMethods
4
- def time_scope(scope)
5
- spawn.time_scope!(scope)
6
- end
7
-
8
- def time_scope!(scope)
9
- self.time_scope_values = time_scope_values.merge(scope)
10
- self
11
- end
12
-
13
- def time_scope_values
14
- @values.fetch(:time_scope, ActiveRecord::QueryMethods::FROZEN_EMPTY_HASH)
15
- end
16
-
17
- def time_scope_values=(scope)
18
- assert_modifiable! # TODO: write test
19
-
20
- @values[:time_scope] = scope
21
- end
22
- end
23
- end
24
- end
@@ -1,38 +0,0 @@
1
- module ActiveRecord::Temporal
2
- module AsOfQuery
3
- class ScopeRegistry
4
- class << self
5
- delegate :default_scopes, :query_scopes, :set_default_scopes, :query_scope_for, :with_query_scope, to: :instance
6
-
7
- def instance
8
- ActiveSupport::IsolatedExecutionState[:temporal_as_of_query_registry] ||= new
9
- end
10
- end
11
-
12
- attr_reader :default_scopes, :query_scopes
13
-
14
- def initialize
15
- @default_scopes = {}
16
- @query_scopes = {}
17
- end
18
-
19
- def set_default_scopes(default_scopes)
20
- @default_scopes = default_scopes
21
- end
22
-
23
- def query_scope_for(dimensions)
24
- query_scopes.slice(*dimensions)
25
- end
26
-
27
- def with_query_scope(scope, &block)
28
- original = @query_scopes.dup
29
-
30
- @query_scopes = @query_scopes.merge(scope)
31
-
32
- block.call
33
- ensure
34
- @query_scopes = original
35
- end
36
- end
37
- end
38
- end
@@ -1,109 +0,0 @@
1
- module ActiveRecord::Temporal
2
- module AsOfQuery
3
- class RangeError < StandardError; end
4
-
5
- extend ActiveSupport::Concern
6
-
7
- class_methods do
8
- def existed_at_constraint(arel_table, time, time_dimension)
9
- time_as_tstz = Arel::Nodes::As.new(
10
- Arel::Nodes::Quoted.new(time),
11
- Arel::Nodes::SqlLiteral.new("timestamptz")
12
- )
13
-
14
- cast_value = Arel::Nodes::NamedFunction.new("CAST", [time_as_tstz])
15
-
16
- arel_table[time_dimension].contains(cast_value)
17
- end
18
-
19
- def temporal_association_scope(&block)
20
- AssociationScope.build(block)
21
- end
22
-
23
- def resolve_time_scopes(time_or_time_scopes)
24
- return time_or_time_scopes if time_or_time_scopes.is_a?(Hash)
25
-
26
- {default_time_dimension.to_sym => time_or_time_scopes}
27
- end
28
- end
29
-
30
- included do
31
- include AssociationMacros
32
- include TimeDimensions
33
-
34
- delegate :resolve_time_scopes, to: :class
35
-
36
- scope :as_of, ->(time) do
37
- time_scopes = resolve_time_scopes(time)
38
-
39
- existed_at(time_scopes).time_scope(time_scopes)
40
- end
41
-
42
- scope :existed_at, ->(time) do
43
- time_scopes = resolve_time_scopes(time)
44
-
45
- rel = all
46
-
47
- time_scopes.each do |time_dimension, time|
48
- next unless time_dimension_column?(time_dimension)
49
-
50
- rel = rel.where(existed_at_constraint(table, time, time_dimension))
51
- end
52
-
53
- rel
54
- end
55
- end
56
-
57
- def time_scopes
58
- @time_scopes || {}
59
- end
60
-
61
- def time_scopes=(value)
62
- @time_scopes = value&.slice(*time_dimensions)
63
- end
64
-
65
- def time_scope
66
- time_scopes[default_time_dimension]
67
- end
68
-
69
- def time_scopes_for(time_dimensions)
70
- time_scopes.slice(*time_dimensions)
71
- end
72
-
73
- def as_of!(time)
74
- time_scopes = resolve_time_scopes(time)
75
-
76
- ensure_time_scopes_in_bounds!(time_scopes)
77
-
78
- reload
79
-
80
- self.time_scopes = time_scopes
81
- end
82
-
83
- def as_of(time)
84
- time_scopes = resolve_time_scopes(time)
85
-
86
- self.class.as_of(time_scopes).find_by(self.class.primary_key => [id])
87
- end
88
-
89
- def initialize_time_scope_from_relation(relation)
90
- associations = relation.includes_values | relation.eager_load_values
91
-
92
- self.time_scopes = relation.time_scope_values
93
-
94
- AssociationWalker.each_target(self, associations) do |target|
95
- target.time_scopes = relation.time_scope_values
96
- end
97
- end
98
-
99
- private
100
-
101
- def ensure_time_scopes_in_bounds!(time_scopes)
102
- time_scopes.each do |dimension, time|
103
- if time_dimension_column?(dimension) && !time_dimension(dimension).cover?(time)
104
- raise RangeError, "#{time} is outside of '#{dimension}' range"
105
- end
106
- end
107
- end
108
- end
109
- end
@@ -1,37 +0,0 @@
1
- module ActiveRecord::Temporal
2
- module SystemVersioning
3
- module Model
4
- extend ActiveSupport::Concern
5
-
6
- included do
7
- include AsOfQuery
8
-
9
- set_time_dimensions :system_period
10
-
11
- reflect_on_all_associations.each do |reflection|
12
- scope = temporal_association_scope(&reflection.scope)
13
-
14
- send(reflection.macro, reflection.name, scope, **reflection.options)
15
- end
16
- end
17
-
18
- class_methods do
19
- def polymorphic_class_for(name)
20
- super.version_model
21
- end
22
-
23
- def sti_name
24
- superclass.sti_name
25
- end
26
-
27
- def find_sti_class(type_name)
28
- superclass.send(:find_sti_class, type_name).version_model
29
- end
30
-
31
- def finder_needs_type_condition?
32
- superclass.finder_needs_type_condition?
33
- end
34
- end
35
- end
36
- end
37
- end
@@ -1,34 +0,0 @@
1
- module ActiveRecord::Temporal
2
- module SystemVersioning
3
- module Namespace
4
- extend ActiveSupport::Concern
5
-
6
- class_methods do
7
- def const_missing(name)
8
- model = name.to_s.constantize
9
- rescue NameError
10
- super
11
- else
12
- unless model.is_a?(Class) && model < ActiveRecord::Base
13
- raise NameError, "#{model} is not a descendent of ActiveRecord::Base"
14
- end
15
-
16
- version_model = if (history_table = model.history_table)
17
- Class.new(model) do
18
- self.table_name = history_table
19
- self.primary_key = model.primary_key_from_db + [:system_period]
20
-
21
- include Model
22
- end
23
- else
24
- Class.new(model) do
25
- include Model
26
- end
27
- end
28
-
29
- const_set(name, version_model)
30
- end
31
- end
32
- end
33
- end
34
- end