annotaterb 4.0.0.beta.1 → 4.1.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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +91 -1
  3. data/VERSION +1 -1
  4. data/lib/annotate_rb/model_annotator/annotation_decider.rb +62 -0
  5. data/lib/annotate_rb/model_annotator/annotation_generator.rb +94 -0
  6. data/lib/annotate_rb/model_annotator/annotator.rb +27 -31
  7. data/lib/annotate_rb/model_annotator/column_annotation_builder.rb +92 -0
  8. data/lib/annotate_rb/model_annotator/column_attributes_builder.rb +102 -0
  9. data/lib/annotate_rb/model_annotator/column_type_builder.rb +51 -0
  10. data/lib/annotate_rb/model_annotator/column_wrapper.rb +84 -0
  11. data/lib/annotate_rb/model_annotator/constants.rb +2 -2
  12. data/lib/annotate_rb/model_annotator/file_annotator.rb +6 -2
  13. data/lib/annotate_rb/model_annotator/file_annotator_instruction.rb +17 -0
  14. data/lib/annotate_rb/model_annotator/foreign_key_annotation_builder.rb +55 -0
  15. data/lib/annotate_rb/model_annotator/helper.rb +75 -22
  16. data/lib/annotate_rb/model_annotator/index_annotation_builder.rb +74 -0
  17. data/lib/annotate_rb/model_annotator/model_file_annotator.rb +21 -84
  18. data/lib/annotate_rb/model_annotator/model_files_getter.rb +4 -2
  19. data/lib/annotate_rb/model_annotator/model_wrapper.rb +155 -0
  20. data/lib/annotate_rb/model_annotator/related_files_list_builder.rb +137 -0
  21. data/lib/annotate_rb/model_annotator.rb +11 -1
  22. data/lib/annotate_rb/options.rb +16 -9
  23. data/lib/annotate_rb/parser.rb +1 -15
  24. data/lib/annotate_rb.rb +0 -1
  25. data/lib/generators/annotate_rb/install/USAGE +7 -0
  26. data/lib/generators/annotate_rb/install/install_generator.rb +14 -0
  27. metadata +18 -9
  28. data/lib/annotate_rb/env.rb +0 -30
  29. data/lib/annotate_rb/model_annotator/schema_info.rb +0 -480
  30. data/lib/generators/annotate_rb/USAGE +0 -4
  31. data/lib/generators/annotate_rb/install_generator.rb +0 -15
  32. /data/lib/generators/annotate_rb/{templates/auto_annotate_models.rake → install/templates/annotate_rb.rake} +0 -0
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnnotateRb
4
+ module ModelAnnotator
5
+ class ModelWrapper
6
+ # Should be the wrapper for an ActiveRecord model that serves as the source of truth of the model
7
+ # of the model that we're annotating
8
+
9
+ def initialize(klass, options = {})
10
+ @klass = klass
11
+ @options = options
12
+ end
13
+
14
+ # Gets the columns of the ActiveRecord model, processes them, and then returns them.
15
+ def columns
16
+ @columns ||= begin
17
+ cols = raw_columns
18
+ cols += translated_columns
19
+
20
+ ignore_columns = @options[:ignore_columns]
21
+ if ignore_columns
22
+ cols = cols.reject do |col|
23
+ col.name.match(/#{ignore_columns}/)
24
+ end
25
+ end
26
+
27
+ cols = cols.sort_by(&:name) if @options[:sort]
28
+ cols = classified_sort(cols) if @options[:classified_sort]
29
+
30
+ cols
31
+ end
32
+ end
33
+
34
+ def connection
35
+ @klass.connection
36
+ end
37
+
38
+ # Returns the unmodified model columns
39
+ def raw_columns
40
+ @raw_columns ||= @klass.columns
41
+ end
42
+
43
+ def primary_key
44
+ @klass.primary_key
45
+ end
46
+
47
+ def table_exists?
48
+ @klass.table_exists?
49
+ end
50
+
51
+ def column_defaults
52
+ @klass.column_defaults
53
+ end
54
+
55
+ # Add columns managed by the globalize gem if this gem is being used.
56
+ # TODO: Audit if this is still needed, it seems like Globalize gem is no longer maintained
57
+ def translated_columns
58
+ return [] unless @klass.respond_to?(:translation_class)
59
+
60
+ ignored_cols = ignored_translation_table_columns
61
+
62
+ @klass.translation_class.columns.reject do |col|
63
+ ignored_cols.include? col.name.to_sym
64
+ end
65
+ end
66
+
67
+ def table_name
68
+ @klass.table_name
69
+ end
70
+
71
+ def model_name
72
+ @klass.name.underscore
73
+ end
74
+
75
+ # Calculates the max width of the schema for the model by looking at the columns, schema comments, with respect
76
+ # to the options.
77
+ def max_schema_info_width
78
+ cols = columns
79
+
80
+ if with_comments?
81
+ max_size = cols.map do |column|
82
+ column.name.size + (column.comment ? Helper.width(column.comment) : 0)
83
+ end.max || 0
84
+ max_size += 2
85
+ else
86
+ max_size = cols.map(&:name).map(&:size).max
87
+ end
88
+ max_size += @options[:format_rdoc] ? 5 : 1
89
+
90
+ max_size
91
+ end
92
+
93
+ def retrieve_indexes_from_table
94
+ table_name = @klass.table_name
95
+ return [] unless table_name
96
+
97
+ indexes = @klass.connection.indexes(table_name)
98
+ return indexes if indexes.any? || !@klass.table_name_prefix
99
+
100
+ # Try to search the table without prefix
101
+ table_name_without_prefix = table_name.to_s.sub(@klass.table_name_prefix, '')
102
+ @klass.connection.indexes(table_name_without_prefix)
103
+ end
104
+
105
+ def with_comments?
106
+ @options[:with_comment] &&
107
+ raw_columns.first.respond_to?(:comment) &&
108
+ raw_columns.map(&:comment).any? { |comment| !comment.nil? }
109
+ end
110
+
111
+ def classified_sort(cols)
112
+ rest_cols = []
113
+ timestamps = []
114
+ associations = []
115
+ id = nil
116
+
117
+ cols.each do |c|
118
+ if c.name.eql?('id')
119
+ id = c
120
+ elsif c.name.eql?('created_at') || c.name.eql?('updated_at')
121
+ timestamps << c
122
+ elsif c.name[-3, 3].eql?('_id')
123
+ associations << c
124
+ else
125
+ rest_cols << c
126
+ end
127
+ end
128
+ [rest_cols, timestamps, associations].each { |a| a.sort_by!(&:name) }
129
+
130
+ ([id] << rest_cols << timestamps << associations).flatten.compact
131
+ end
132
+
133
+ # These are the columns that the globalize gem needs to work but
134
+ # are not necessary for the models to be displayed as annotations.
135
+ def ignored_translation_table_columns
136
+ # Construct the foreign column name in the translations table
137
+ # eg. Model: Car, foreign column name: car_id
138
+ foreign_column_name = [
139
+ @klass.translation_class.to_s
140
+ .gsub('::Translation', '').gsub('::', '_')
141
+ .downcase,
142
+ '_id'
143
+ ].join.to_sym
144
+
145
+ [
146
+ :id,
147
+ :created_at,
148
+ :updated_at,
149
+ :locale,
150
+ foreign_column_name
151
+ ]
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnnotateRb
4
+ module ModelAnnotator
5
+ # Given a model file and options, this class will return a list of related files (e.g. fixture, controllers, etc)
6
+ # to also annotate
7
+ class RelatedFilesListBuilder
8
+ RELATED_TYPES = %w(test fixture factory serializer scaffold controller helper).freeze
9
+
10
+ def initialize(file, model_name, table_name, options)
11
+ @file = file
12
+ @model_name = model_name
13
+ @table_name = table_name
14
+ @options = options
15
+ end
16
+
17
+ def build
18
+ @list = []
19
+
20
+ add_related_test_files if !@options[:exclude_tests]
21
+ add_related_fixture_files if !@options[:exclude_fixtures]
22
+ add_related_factory_files if !@options[:exclude_factories]
23
+ add_related_serializer_files if !@options[:exclude_serializers]
24
+ add_related_scaffold_files if !@options[:exclude_scaffolds]
25
+ add_related_controller_files if !@options[:exclude_controllers]
26
+ add_related_helper_files if !@options[:exclude_helpers]
27
+ add_related_admin_files if !@options[:active_admin]
28
+ add_additional_file_patterns if !@options[:additional_file_patterns].present?
29
+
30
+ @list
31
+ end
32
+
33
+ private
34
+
35
+ def related_files_for_pattern(pattern_type)
36
+ patterns = PatternGetter.call(@options, pattern_type)
37
+
38
+ _related_files = patterns
39
+ .map { |f| FileNameResolver.call(f, @model_name, @table_name) }
40
+ .map { |f| Dir.glob(f) }
41
+ .flatten
42
+
43
+ _related_files
44
+ end
45
+
46
+ def add_related_test_files
47
+ position_key = :position_in_test
48
+ pattern_type = 'test'
49
+
50
+ related_files = related_files_for_pattern(pattern_type)
51
+ files_with_position_key = related_files.map { |f| [f, position_key] }
52
+
53
+ @list.concat(files_with_position_key)
54
+ end
55
+
56
+ def add_related_fixture_files
57
+ position_key = :position_in_fixture
58
+ pattern_type = 'fixture'
59
+
60
+ related_files = related_files_for_pattern(pattern_type)
61
+ files_with_position_key = related_files.map { |f| [f, position_key] }
62
+
63
+ @list.concat(files_with_position_key)
64
+ end
65
+
66
+ def add_related_factory_files
67
+ position_key = :position_in_factory
68
+ pattern_type = 'factory'
69
+
70
+ related_files = related_files_for_pattern(pattern_type)
71
+ files_with_position_key = related_files.map { |f| [f, position_key] }
72
+
73
+ @list.concat(files_with_position_key)
74
+ end
75
+
76
+ def add_related_serializer_files
77
+ position_key = :position_in_serializer
78
+ pattern_type = 'serializer'
79
+
80
+ related_files = related_files_for_pattern(pattern_type)
81
+ files_with_position_key = related_files.map { |f| [f, position_key] }
82
+
83
+ @list.concat(files_with_position_key)
84
+ end
85
+
86
+ def add_related_scaffold_files
87
+ position_key = :position_in_scaffold # Key does not exist
88
+ pattern_type = 'scaffold'
89
+
90
+ related_files = related_files_for_pattern(pattern_type)
91
+ files_with_position_key = related_files.map { |f| [f, position_key] }
92
+
93
+ @list.concat(files_with_position_key)
94
+ end
95
+
96
+ def add_related_controller_files
97
+ position_key = :position_in_controller # Key does not exist
98
+ pattern_type = 'controller'
99
+
100
+ related_files = related_files_for_pattern(pattern_type)
101
+ files_with_position_key = related_files.map { |f| [f, position_key] }
102
+
103
+ @list.concat(files_with_position_key)
104
+ end
105
+
106
+ def add_related_helper_files
107
+ position_key = :position_in_helper # Key does not exist
108
+ pattern_type = 'helper'
109
+
110
+ related_files = related_files_for_pattern(pattern_type)
111
+ files_with_position_key = related_files.map { |f| [f, position_key] }
112
+
113
+ @list.concat(files_with_position_key)
114
+ end
115
+
116
+ def add_related_admin_files
117
+ position_key = :position_in_admin # Key does not exist
118
+ pattern_type = 'admin'
119
+
120
+ related_files = related_files_for_pattern(pattern_type)
121
+ files_with_position_key = related_files.map { |f| [f, position_key] }
122
+
123
+ @list.concat(files_with_position_key)
124
+ end
125
+
126
+ def add_additional_file_patterns
127
+ position_key = :position_in_additional_file_patterns # Key does not exist
128
+ pattern_type = 'additional_file_patterns'
129
+
130
+ related_files = related_files_for_pattern(pattern_type)
131
+ files_with_position_key = related_files.map { |f| [f, position_key] }
132
+
133
+ @list.concat(files_with_position_key)
134
+ end
135
+ end
136
+ end
137
+ end
@@ -6,7 +6,6 @@ module AnnotateRb
6
6
  autoload :Helper, 'annotate_rb/model_annotator/helper'
7
7
  autoload :FilePatterns, 'annotate_rb/model_annotator/file_patterns'
8
8
  autoload :Constants, 'annotate_rb/model_annotator/constants'
9
- autoload :SchemaInfo, 'annotate_rb/model_annotator/schema_info'
10
9
  autoload :PatternGetter, 'annotate_rb/model_annotator/pattern_getter'
11
10
  autoload :BadModelFileError, 'annotate_rb/model_annotator/bad_model_file_error'
12
11
  autoload :FileNameResolver, 'annotate_rb/model_annotator/file_name_resolver'
@@ -16,5 +15,16 @@ module AnnotateRb
16
15
  autoload :ModelFilesGetter, 'annotate_rb/model_annotator/model_files_getter'
17
16
  autoload :FileAnnotator, 'annotate_rb/model_annotator/file_annotator'
18
17
  autoload :ModelFileAnnotator, 'annotate_rb/model_annotator/model_file_annotator'
18
+ autoload :ModelWrapper, 'annotate_rb/model_annotator/model_wrapper'
19
+ autoload :AnnotationGenerator, 'annotate_rb/model_annotator/annotation_generator'
20
+ autoload :ColumnAttributesBuilder, 'annotate_rb/model_annotator/column_attributes_builder'
21
+ autoload :ColumnTypeBuilder, 'annotate_rb/model_annotator/column_type_builder'
22
+ autoload :ColumnWrapper, 'annotate_rb/model_annotator/column_wrapper'
23
+ autoload :ColumnAnnotationBuilder, 'annotate_rb/model_annotator/column_annotation_builder'
24
+ autoload :IndexAnnotationBuilder, 'annotate_rb/model_annotator/index_annotation_builder'
25
+ autoload :ForeignKeyAnnotationBuilder, 'annotate_rb/model_annotator/foreign_key_annotation_builder'
26
+ autoload :RelatedFilesListBuilder, 'annotate_rb/model_annotator/related_files_list_builder'
27
+ autoload :AnnotationDecider, 'annotate_rb/model_annotator/annotation_decider'
28
+ autoload :FileAnnotatorInstruction, 'annotate_rb/model_annotator/file_annotator_instruction'
19
29
  end
20
30
  end
@@ -26,14 +26,14 @@ module AnnotateRb
26
26
 
27
27
  FLAG_OPTIONS = {
28
28
  classified_sort: true, # ModelAnnotator
29
- exclude_controllers: true, # Unused
30
- exclude_factories: false, # Unused
31
- exclude_fixtures: false, # Unused
32
- exclude_helpers: true, # Unused
33
- exclude_scaffolds: true, # Unused
34
- exclude_serializers: false, # Unused
29
+ exclude_controllers: true, # ModelAnnotator
30
+ exclude_factories: false, # ModelAnnotator
31
+ exclude_fixtures: false, # ModelAnnotator
32
+ exclude_helpers: true, # ModelAnnotator
33
+ exclude_scaffolds: true, # ModelAnnotator
34
+ exclude_serializers: false, # ModelAnnotator
35
35
  exclude_sti_subclasses: false, # ModelAnnotator
36
- exclude_tests: false, # Unused
36
+ exclude_tests: false, # ModelAnnotator
37
37
  force: false, # ModelAnnotator, but should be used by both
38
38
  format_bare: true, # Unused
39
39
  format_markdown: false, # ModelAnnotator, RouteAnnotator
@@ -59,10 +59,10 @@ module AnnotateRb
59
59
  debug: false, # Core
60
60
 
61
61
  # ModelAnnotator
62
- hide_default_column_types: '<%= ::AnnotateRb::ModelAnnotator::SchemaInfo::NO_DEFAULT_COL_TYPES.join(",") %>',
62
+ hide_default_column_types: '',
63
63
 
64
64
  # ModelAnnotator
65
- hide_limit_column_types: '<%= ::AnnotateRb::ModelAnnotator::SchemaInfo::NO_LIMIT_COL_TYPES.join(",") %>',
65
+ hide_limit_column_types: '',
66
66
 
67
67
  ignore_columns: nil, # ModelAnnotator
68
68
  ignore_routes: nil, # RouteAnnotator
@@ -95,7 +95,14 @@ module AnnotateRb
95
95
 
96
96
  FLAG_OPTION_KEYS = [
97
97
  :classified_sort,
98
+ :exclude_controllers,
99
+ :exclude_factories,
100
+ :exclude_fixtures,
101
+ :exclude_helpers,
102
+ :exclude_scaffolds,
103
+ :exclude_serializers,
98
104
  :exclude_sti_subclasses,
105
+ :exclude_tests,
99
106
  :force,
100
107
  :format_markdown,
101
108
  :format_rdoc,
@@ -78,7 +78,7 @@ module AnnotateRb
78
78
  # TODO: Should raise or alert user that multiple commands were selected but only 1 command will be ran
79
79
  @options[:command] = map[@commands.first]
80
80
  else # None
81
- @options[:command] = nil
81
+ @options[:command] = map[:help]
82
82
  end
83
83
  end
84
84
 
@@ -156,13 +156,6 @@ module AnnotateRb
156
156
  option_parser.separator(' ' * 4 + 'Usage: annotaterb models [options]')
157
157
  option_parser.separator('')
158
158
 
159
- # option_parser.on('-m',
160
- # '--models',
161
- # "Annotate ActiveRecord models") do
162
- # @options[:models] = true
163
- # @options[:command] = Commands::AnnotateModels.new
164
- # end
165
-
166
159
  option_parser.on('-a',
167
160
  '--active-admin',
168
161
  'Annotate active_admin models') do
@@ -232,13 +225,6 @@ module AnnotateRb
232
225
  option_parser.separator(' ' * 4 + 'Usage: annotaterb routes [options]')
233
226
  option_parser.separator('')
234
227
 
235
- # option_parser.on('-r',
236
- # '--routes',
237
- # "Annotate routes.rb with the output of 'rails routes'") do
238
- # @options[:routes] = true
239
- # @options[:command] = Commands::AnnotateRoutes.new
240
- # end
241
-
242
228
  option_parser.on('--ignore-routes REGEX',
243
229
  "don't annotate routes that match a given REGEX (i.e., `annotate -I '(mobile|resque|pghero)'`") do |regex|
244
230
  @options[:ignore_routes] = regex
data/lib/annotate_rb.rb CHANGED
@@ -18,7 +18,6 @@ require_relative 'annotate_rb/parser'
18
18
  require_relative 'annotate_rb/runner'
19
19
  require_relative 'annotate_rb/route_annotator'
20
20
  require_relative 'annotate_rb/model_annotator'
21
- require_relative 'annotate_rb/env'
22
21
  require_relative 'annotate_rb/options'
23
22
  require_relative 'annotate_rb/eager_loader'
24
23
  require_relative 'annotate_rb/rake_bootstrapper'
@@ -0,0 +1,7 @@
1
+ Description:
2
+ Generates a default configuration file and adds a rake task into
3
+ your Rails app's lib/tasks directory, that automatically
4
+ annotates models when you do a db:migrate in development mode.
5
+
6
+ Example:
7
+ `rails generate annotate_rb:install`
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ require 'annotate_rb'
3
+
4
+ module AnnotateRb
5
+ module Generators
6
+ class InstallGenerator < ::Rails::Generators::Base
7
+ source_root File.expand_path('templates', __dir__)
8
+
9
+ def copy_task
10
+ copy_file "annotate_rb.rake", "lib/tasks/annotate_rb.rake"
11
+ end
12
+ end
13
+ end
14
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: annotaterb
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0.beta.1
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew W. Lee
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-04-26 00:00:00.000000000 Z
11
+ date: 2023-05-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Annotates Rails/ActiveRecord Models, routes, fixtures, and others based
14
14
  on the database schema.
@@ -35,22 +35,31 @@ files:
35
35
  - lib/annotate_rb/config_loader.rb
36
36
  - lib/annotate_rb/core.rb
37
37
  - lib/annotate_rb/eager_loader.rb
38
- - lib/annotate_rb/env.rb
39
38
  - lib/annotate_rb/model_annotator.rb
39
+ - lib/annotate_rb/model_annotator/annotation_decider.rb
40
+ - lib/annotate_rb/model_annotator/annotation_generator.rb
40
41
  - lib/annotate_rb/model_annotator/annotation_pattern_generator.rb
41
42
  - lib/annotate_rb/model_annotator/annotator.rb
42
43
  - lib/annotate_rb/model_annotator/bad_model_file_error.rb
44
+ - lib/annotate_rb/model_annotator/column_annotation_builder.rb
45
+ - lib/annotate_rb/model_annotator/column_attributes_builder.rb
46
+ - lib/annotate_rb/model_annotator/column_type_builder.rb
47
+ - lib/annotate_rb/model_annotator/column_wrapper.rb
43
48
  - lib/annotate_rb/model_annotator/constants.rb
44
49
  - lib/annotate_rb/model_annotator/file_annotation_remover.rb
45
50
  - lib/annotate_rb/model_annotator/file_annotator.rb
51
+ - lib/annotate_rb/model_annotator/file_annotator_instruction.rb
46
52
  - lib/annotate_rb/model_annotator/file_name_resolver.rb
47
53
  - lib/annotate_rb/model_annotator/file_patterns.rb
54
+ - lib/annotate_rb/model_annotator/foreign_key_annotation_builder.rb
48
55
  - lib/annotate_rb/model_annotator/helper.rb
56
+ - lib/annotate_rb/model_annotator/index_annotation_builder.rb
49
57
  - lib/annotate_rb/model_annotator/model_class_getter.rb
50
58
  - lib/annotate_rb/model_annotator/model_file_annotator.rb
51
59
  - lib/annotate_rb/model_annotator/model_files_getter.rb
60
+ - lib/annotate_rb/model_annotator/model_wrapper.rb
52
61
  - lib/annotate_rb/model_annotator/pattern_getter.rb
53
- - lib/annotate_rb/model_annotator/schema_info.rb
62
+ - lib/annotate_rb/model_annotator/related_files_list_builder.rb
54
63
  - lib/annotate_rb/options.rb
55
64
  - lib/annotate_rb/parser.rb
56
65
  - lib/annotate_rb/rake_bootstrapper.rb
@@ -63,9 +72,9 @@ files:
63
72
  - lib/annotate_rb/route_annotator/removal_processor.rb
64
73
  - lib/annotate_rb/runner.rb
65
74
  - lib/annotate_rb/tasks/annotate_models_migrate.rake
66
- - lib/generators/annotate_rb/USAGE
67
- - lib/generators/annotate_rb/install_generator.rb
68
- - lib/generators/annotate_rb/templates/auto_annotate_models.rake
75
+ - lib/generators/annotate_rb/install/USAGE
76
+ - lib/generators/annotate_rb/install/install_generator.rb
77
+ - lib/generators/annotate_rb/install/templates/annotate_rb.rake
69
78
  homepage: https://github.com/drwl/annotaterb
70
79
  licenses:
71
80
  - BSD-2-Clause
@@ -85,9 +94,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
85
94
  version: 2.7.0
86
95
  required_rubygems_version: !ruby/object:Gem::Requirement
87
96
  requirements:
88
- - - ">"
97
+ - - ">="
89
98
  - !ruby/object:Gem::Version
90
- version: 1.3.1
99
+ version: '0'
91
100
  requirements: []
92
101
  rubygems_version: 3.2.33
93
102
  signing_key:
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AnnotateRb
4
- class Env
5
- class << self
6
- def read(key)
7
- key = key.to_s unless key.is_a?(String)
8
-
9
- ENV[key]
10
- end
11
-
12
- def write(key, value)
13
- key = key.to_s unless key.is_a?(String)
14
-
15
- ENV[key] = value.to_s
16
- end
17
-
18
- def fetch(key, default_value)
19
- key = key.to_s unless key.is_a?(String)
20
- val = read(key)
21
-
22
- if val.nil?
23
- default_value
24
- else
25
- val
26
- end
27
- end
28
- end
29
- end
30
- end