annotaterb 4.0.0.beta.1 → 4.1.0

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