k_doc 0.0.4 → 0.0.10

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.
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This could move into KDecor
4
+ module KDoc
5
+ module Decorators
6
+ class SettingsDecorator < KDecor::BaseDecorator
7
+ def initialize
8
+ super(KDoc::Settings)
9
+ end
10
+
11
+ # def update(target, behaviour)
12
+ # update_settings(target, target.internal_data) if %i[all default].include?(behaviour)
13
+
14
+ # target
15
+ # end
16
+
17
+ # # What responsibility will this SettingsDecorator take on?
18
+ # def update(target, **_opts)
19
+ # def update_settings(_target, _settings)
20
+ # log.warn('Override this method in your descendant implementation')
21
+ # end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KDoc
4
+ module Decorators
5
+ class TableDecorator < KDecor::BaseDecorator
6
+ def initialize
7
+ super(KDoc::Table)
8
+
9
+ self.implemented_behaviours = %i[update_fields update_rows]
10
+ end
11
+
12
+ def update(target, **opts)
13
+ behaviour = opts[:behaviour]
14
+
15
+ update_fields(target, target.get_fields) if %i[all update_fields].include?(behaviour)
16
+ update_rows(target, target.get_rows) if %i[all update_rows].include?(behaviour)
17
+
18
+ target
19
+ end
20
+
21
+ # What responsibility will this TableDecorator take on?
22
+ # Update fields/columns, or/and
23
+ def update_fields(_target, _fields)
24
+ raise KType::Error, 'Update fields not implement, you need to implement this method and '
25
+ end
26
+
27
+ # Update row values/structure
28
+ def update_rows(_target, _rows); end
29
+ end
30
+ end
31
+ end
@@ -10,7 +10,7 @@ module KDoc
10
10
  attr_accessor :default_settings_key
11
11
  attr_accessor :default_table_key
12
12
 
13
- attr_accessor :document_class
13
+ # attr_accessor :document_class
14
14
  attr_accessor :settings_class
15
15
  attr_accessor :table_class
16
16
 
@@ -19,7 +19,7 @@ module KDoc
19
19
  @default_settings_key = :settings
20
20
  @default_table_key = :table
21
21
 
22
- @document_class = KDoc::Document
22
+ # @document_class = KDoc::Document
23
23
  @table_class = KDoc::Table
24
24
  @settings_class = KDoc::Settings
25
25
  end
@@ -6,8 +6,12 @@ module KDoc
6
6
  # Builds up key/value settings from the block
7
7
  # and applies them to a key coded node on the hash
8
8
  class Settings
9
+ include KLog::Logging
10
+ # include KDoc::Decorators
11
+
9
12
  attr_reader :parent
10
13
  attr_reader :key
14
+ attr_reader :decorators
11
15
 
12
16
  alias kp parent
13
17
 
@@ -17,6 +21,9 @@ module KDoc
17
21
  # Need a way to find out the line number for errors and report it correctly
18
22
  begin
19
23
  instance_eval(&block) if block_given?
24
+
25
+ run_decorators
26
+
20
27
  # rubocop:disable Style/RescueStandardError
21
28
  rescue => e
22
29
  # rubocop:enable Style/RescueStandardError
@@ -26,27 +33,19 @@ module KDoc
26
33
  end
27
34
  end
28
35
 
29
- def my_data
36
+ # Return these settings which are attached to a data container using :key
37
+ # internal_data is a bad name, but it is unlikely to interfere with any setting names
38
+ # Maybe I rename this to raw_data
39
+ def internal_data
30
40
  @data[@key]
31
41
  end
32
42
 
33
- # def run_decorators(opts)
34
- # decorators = KDoc::Decorator.decorate.decorators(opts[:decorators])
35
-
36
- # return if decorators.empty?
37
-
38
- # decorators.each do |decorator|
39
- # decorator.send(:update, my_data) if decorator.respond_to?(:update)
40
- # decorator.send(:call, my_data) if decorator.respond_to?(:call)
41
- # end
42
- # end
43
-
44
43
  def respond_to_missing?(name, *_args, &_block)
45
44
  # puts 'respond_to_missing?'
46
45
  # puts "respond_to_missing: #{name}"
47
46
  n = name.to_s
48
47
  n = n[0..-2] if n.end_with?('=')
49
- my_data.key?(n.to_s) || (!@parent.nil? && @parent.respond_to?(name, true)) || super
48
+ internal_data.key?(n.to_s) || (!@parent.nil? && @parent.respond_to?(name, true)) || super
50
49
  end
51
50
 
52
51
  # rubocop:disable Metrics/AbcSize
@@ -73,14 +72,14 @@ module KDoc
73
72
  # object.my_name
74
73
  # object.my_name('david')
75
74
  def add_getter_or_param_method(name)
76
- # L.progress(1, 'add_getter_or_param_method')
75
+ # log.progress(1, 'add_getter_or_param_method')
77
76
  self.class.class_eval do
78
- # L.progress(2, 'add_getter_or_param_method')
77
+ # log.progress(2, 'add_getter_or_param_method')
79
78
  name = name.to_s.gsub(/=$/, '')
80
- # L.progress(3, 'add_getter_or_param_method')
79
+ # log.progress(3, 'add_getter_or_param_method')
81
80
  define_method(name) do |*args|
82
- # L.progress(4, 'add_getter_or_param_method')
83
- # L.kv 'add_getter_or_param_method', name
81
+ # log.progress(4, 'add_getter_or_param_method')
82
+ # log.kv 'add_getter_or_param_method', name
84
83
  raise KDoc::Error, 'Multiple setting values is not supported' if args.length > 1
85
84
 
86
85
  if args.length.zero?
@@ -95,35 +94,48 @@ module KDoc
95
94
  # Handles Setter method
96
95
  # object.my_name = 'david'
97
96
  def add_setter_method(name)
98
- # L.progress(1, 'add_setter_method')
97
+ # log.progress(1, 'add_setter_method')
99
98
  self.class.class_eval do
100
- # L.progress(2, 'add_setter_method')
99
+ # log.progress(2, 'add_setter_method')
101
100
  name = name.to_s.gsub(/=$/, '')
102
- # L.progress(3, 'add_setter_method')
103
- # L.kv 'add_setter_method', name
101
+ # log.progress(3, 'add_setter_method')
102
+ # log.kv 'add_setter_method', name
104
103
  define_method("#{name}=") do |value|
105
- # L.progress(4, 'add_setter_method')
106
- # L.kv 'value', value
107
- my_data[name.to_s] = value
104
+ # log.progress(4, 'add_setter_method')
105
+ # log.kv 'value', value
106
+ internal_data[name.to_s] = value
108
107
  end
109
108
  end
110
109
  end
111
110
 
112
111
  def get_value(name)
113
- my_data[name.to_s]
112
+ internal_data[name.to_s]
114
113
  end
115
114
 
116
115
  def debug
117
- puts JSON.pretty_generate(my_data)
116
+ puts JSON.pretty_generate(internal_data)
118
117
  end
119
118
 
120
119
  private
121
120
 
121
+ # This method can move into decorator helpers
122
+ def run_decorators
123
+ decorators.each { |decorator| decorator.decorate(self, :settings) }
124
+ end
125
+
122
126
  def initialize_attributes(data, key = nil, **options)
123
127
  @data = data
124
128
  @key = (key || FakeOpinion.new.default_settings_key).to_s
125
129
 
126
- @parent = options[:parent] if !options.nil? && options.key?(:parent)
130
+ @parent = options[:parent] if options.key?(:parent)
131
+
132
+ decorator_list = options[:decorators].nil? ? [] : options[:decorators]
133
+
134
+ # This code needs to work differently, it needs to support the 3 different types
135
+ # Move the query into helpers
136
+ @decorators = decorator_list
137
+ .map(&:new)
138
+ .select { |decorator| decorator.compatible?(self) }
127
139
 
128
140
  @data[@key] = {}
129
141
  end
data/lib/k_doc/table.rb CHANGED
@@ -3,16 +3,33 @@
3
3
  module KDoc
4
4
  # Build rows (aka DataTable) with field definitions and rows of data
5
5
  class Table
6
+ include KLog::Logging
7
+
6
8
  attr_reader :parent
7
9
  attr_reader :name
10
+ attr_reader :decorators
8
11
 
9
12
  def initialize(data, name = nil, **options, &block)
10
13
  initialize_attributes(data, name, **options)
11
14
 
15
+ @has_executed_field_decorators = false
16
+ @has_executed_row_decorators = false
17
+
12
18
  instance_eval(&block) if block_given?
19
+
20
+ run_decorators(:update_rows)
13
21
  end
14
22
 
15
- def fields(field_definitions)
23
+ # Pass fields in using the following format
24
+ # fields :name, f(:type, :string), :db_type
25
+ #
26
+ # The older format of an array is supported via a splat conversion
27
+ def fields(*field_definitions)
28
+ if field_definitions.length == 1 && field_definitions[0].is_a?(Array)
29
+ log.warn('avoid supplying field definitions with array. *Splat fields is the preferred technique.')
30
+ field_definitions = *field_definitions[0]
31
+ end
32
+
16
33
  fields = @data[@name]['fields']
17
34
 
18
35
  field_definitions.each do |fd|
@@ -22,15 +39,18 @@ module KDoc
22
39
  fd
23
40
  end
24
41
  end
42
+
43
+ run_decorators(:update_fields)
25
44
  end
26
45
 
27
46
  # rubocop:disable Metrics/AbcSize
28
47
  def row(*args, **named_args)
29
48
  fields = @data[@name]['fields']
30
49
 
31
- raise "To many values for row, argument #{i}" if args.length > fields.length
50
+ raise KType::Error, "To many values for row, argument #{args.length}" if args.length > fields.length
32
51
 
33
52
  # Apply column names with defaults
53
+
34
54
  row = fields.each_with_object({}) do |f, hash|
35
55
  hash[f['name']] = f['default']
36
56
  end
@@ -60,6 +80,10 @@ module KDoc
60
80
  end
61
81
  # rubocop:enable Naming/AccessorMethodName
62
82
 
83
+ def internal_data
84
+ @data[@name]
85
+ end
86
+
63
87
  def find_row(key, value)
64
88
  @data[@name]['rows'].find { |r| r[key] == value }
65
89
  end
@@ -91,16 +115,45 @@ module KDoc
91
115
  end
92
116
  alias f field
93
117
 
118
+ def debug
119
+ log.o(KUtil.data.to_open_struct(internal_data))
120
+ end
121
+
94
122
  private
95
123
 
124
+ # This method can move into decorator helpers
125
+ # Run decorators a maximum of once for each behaviour
126
+ # rubocop:disable Metrics/CyclomaticComplexity
127
+ def run_decorators(behaviour)
128
+ return if behaviour == :update_fields && @has_executed_field_decorators
129
+ return if behaviour == :update_rows && @has_executed_row_decorators
130
+
131
+ @has_executed_field_decorators = true if behaviour == :update_fields
132
+
133
+ @has_executed_rows_decorators = true if behaviour == :update_rows
134
+
135
+ decorators.each { |decorator| decorator.decorate(self, behaviour) }
136
+ end
137
+ # rubocop:enable Metrics/CyclomaticComplexity
138
+
139
+ # rubocop:disable Metrics/AbcSize
96
140
  def initialize_attributes(data, name = nil, **options)
97
141
  @data = data
98
142
  @name = (name || FakeOpinion.new.default_table_key.to_s).to_s
99
143
 
100
144
  @parent = options[:parent] if !options.nil? && options.key?(:parent)
101
145
 
146
+ # This code needs to work differently, it needs to support the 3 different types
147
+ # Move the query into helpers
148
+ decorator_list = options[:decorators].nil? ? [] : options[:decorators]
149
+
150
+ @decorators = decorator_list
151
+ .map(&:new)
152
+ .select { |decorator| decorator.compatible?(self) }
153
+
102
154
  @data[@name] = { 'fields' => [], 'rows' => [] }
103
155
  end
156
+ # rubocop:enable Metrics/AbcSize
104
157
 
105
158
  def respond_to_missing?(name, *_args, &_block)
106
159
  (!@parent.nil? && @parent.respond_to?(name, true)) || super
data/lib/k_doc/util.rb CHANGED
@@ -3,12 +3,18 @@
3
3
  module KDoc
4
4
  # Utility helper methods for KDoc
5
5
  class Util
6
- def build_unique_key(key, type = nil, namespace = nil)
6
+ # Build a unique key so that resources of the same key do not conflict with
7
+ # one another across projects, namespaces or types
8
+ #
9
+ # @param [String] param_name Param description
10
+ def build_unique_key(key, type = nil, namespace = nil, project_key = nil)
7
11
  raise KDoc::Error, 'key is required when generating unique key' if key.nil? || key.empty?
8
12
 
9
13
  type ||= KDoc.opinion.default_document_type
10
14
 
11
- namespace.nil? || namespace.empty? ? "#{key}_#{type}" : "#{namespace}_#{key}_#{type}"
15
+ keys = [project_key, namespace, key, type].reject { |k| k.nil? || k == '' }
16
+
17
+ keys.join('_')
12
18
  end
13
19
  end
14
20
  end
data/lib/k_doc/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KDoc
4
- VERSION = '0.0.4'
4
+ VERSION = '0.0.10'
5
5
  end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: k_doc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Cruwys
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-04-01 00:00:00.000000000 Z
11
+ date: 2021-04-21 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: k_decor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.0.0
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: k_log
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -24,6 +52,20 @@ dependencies:
24
52
  - - "~>"
25
53
  - !ruby/object:Gem::Version
26
54
  version: 0.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: k_type
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.0.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.0.0
27
69
  - !ruby/object:Gem::Dependency
28
70
  name: k_util
29
71
  requirement: !ruby/object:Gem::Requirement
@@ -57,6 +99,7 @@ files:
57
99
  - README.md
58
100
  - Rakefile
59
101
  - STORIES.md
102
+ - ToDo.md
60
103
  - USAGE.md
61
104
  - bin/console
62
105
  - bin/k
@@ -67,8 +110,10 @@ files:
67
110
  - hooks/update-version
68
111
  - k_doc.gemspec
69
112
  - lib/k_doc.rb
113
+ - lib/k_doc/container.rb
70
114
  - lib/k_doc/data.rb
71
- - lib/k_doc/document.rb
115
+ - lib/k_doc/decorators/settings_decorator.rb
116
+ - lib/k_doc/decorators/table_decorator.rb
72
117
  - lib/k_doc/fake_opinion.rb
73
118
  - lib/k_doc/settings.rb
74
119
  - lib/k_doc/table.rb
@@ -1,188 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module KDoc
4
- # General purpose document DSL
5
- #
6
- # Made up of 0 or more setting groups and table groups
7
- class Document
8
- attr_reader :key
9
- attr_reader :type
10
- attr_reader :namespace
11
- attr_reader :options
12
- attr_reader :error
13
-
14
- # Create document
15
- #
16
- # @param [String|Symbol] name Name of the document
17
- # @param args[0] Type of the document, defaults to KDoc:: FakeOpinion.new.default_document_type if not set
18
- # @param default: Default value (using named params), as above
19
- def initialize(key = SecureRandom.alphanumeric(8), **options, &block)
20
- initialize_attributes(key, **options)
21
-
22
- @block = block if block_given?
23
- end
24
-
25
- def execute_block(run_actions: nil)
26
- return if @block.nil?
27
-
28
- # The DSL actions method will only run on run_actions: true
29
- @run_actions = run_actions
30
-
31
- instance_eval(&@block)
32
-
33
- on_action if run_actions && respond_to?(:on_action)
34
- # rescue KDoc::Error => e
35
- # puts('KDoc::Error in document')
36
- # puts "key #{unique_key}"
37
- # # puts "file #{KUtil.data.console_file_hyperlink(resource.file, resource.file)}"
38
- # puts(e.message)
39
- # @error = e
40
- # raise
41
- rescue StandardError => e
42
- L.error('Standard error in document')
43
- puts "key #{unique_key}"
44
- # puts "file #{KUtil.data.console_file_hyperlink(resource.file, resource.file)}"
45
- L.error(e.message)
46
- @error = e
47
- # L.exception exception2
48
- raise
49
- ensure
50
- @run_actions = nil
51
- end
52
-
53
- def unique_key
54
- @unique_key ||= KDoc.util.build_unique_key(key, type, namespace)
55
- end
56
-
57
- def settings(key = nil, **options, &block)
58
- options ||= {}
59
-
60
- opts = {}.merge(@options) # Document Options
61
- .merge(options) # Settings Options
62
- .merge(parent: self)
63
-
64
- settings_instance(@data, key, **opts, &block)
65
- # settings.run_decorators(opts)
66
- end
67
-
68
- def table(key = :table, **options, &block)
69
- # NEED to add support for run_decorators I think
70
- options.merge(parent: self)
71
- table_instance(@data, key, **options, &block)
72
- end
73
- alias rows table
74
-
75
- # Sweet add-on would be builders
76
- # def builder(key, &block)
77
- # # example
78
- # KDoc::Builder::Shotstack.new(@data, key, &block)
79
- # end
80
-
81
- # def set_data(data)
82
- # @data = data
83
- # end
84
-
85
- def data
86
- @data.clone
87
- end
88
-
89
- def data_struct
90
- KUtil.data.to_open_struct(data)
91
- end
92
- # alias d data_struct
93
-
94
- def raw_data_struct
95
- KUtil.data.to_open_struct(raw_data)
96
- end
97
-
98
- def get_node_type(node_name)
99
- node_name = KUtil.data.clean_symbol(node_name)
100
- node_data = @data[node_name]
101
-
102
- raise KDoc::Error, "Node not found: #{node_name}" if node_data.nil?
103
-
104
- if node_data.keys.length == 2 && (node_data.key?('fields') && node_data.key?('rows'))
105
- :table
106
- else
107
- :settings
108
- end
109
- end
110
-
111
- # Removes any meta data eg. "fields" from a table and just returns the raw data
112
- def raw_data
113
- # REFACT, what if this is CSV, meaning it is just an array?
114
- # add specs
115
- result = data
116
-
117
- result.each_key do |key|
118
- # ANTI: get_node_type uses @data while we are using @data.clone here
119
- data[key] = if get_node_type(key) == :table
120
- result[key].delete('fields')
121
- else
122
- result[key]
123
- end
124
- end
125
-
126
- data
127
- end
128
-
129
- # Move this out to the logger function when it has been refactor
130
- def debug(include_header: false)
131
- debug_header if include_header
132
-
133
- # tp dsls.values, :k_key, :k_type, :state, :save_at, :last_at, :data, :last_data, :source, { :file => { :width => 150 } }
134
- # puts JSON.pretty_generate(data)
135
- L.o(raw_data_struct)
136
- end
137
-
138
- def debug_header
139
- L.heading self.class.name
140
- L.kv 'key', key
141
- L.kv 'type', type
142
- L.kv 'namespace', namespace
143
- L.kv 'error', error
144
-
145
- debug_header_keys
146
-
147
- L.line
148
- end
149
-
150
- def debug_header_keys
151
- options&.keys&.reject { |k| k == :namespace }&.each do |key|
152
- L.kv key, options[key]
153
- end
154
- end
155
-
156
- private
157
-
158
- def initialize_attributes(key = nil, **options)
159
- @key = key
160
-
161
- @options = options || {}
162
- @type = slice_option(:type) || KDoc.opinion.default_document_type
163
- @namespace = slice_option(:namespace) || ''
164
- @parent = slice_option(:parent)
165
-
166
- # Most documents live within a hash, some tabular documents such as CSV will use an []
167
- @data = slice_option(:default_data) || {}
168
-
169
- @error = nil
170
- end
171
-
172
- def settings_instance(data, key, **options, &block)
173
- KDoc.opinion.settings_class.new(data, key, **options, &block)
174
- end
175
-
176
- def table_instance(data, key, **options, &block)
177
- KDoc.opinion.table_class.new(data, key, **options, &block)
178
- end
179
-
180
- def slice_option(key)
181
- return nil unless @options.key?(key)
182
-
183
- result = @options[key]
184
- @options.delete(key)
185
- result
186
- end
187
- end
188
- end