k_doc 0.0.5 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.5'
4
+ VERSION = '0.0.11'
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.5
4
+ version: 0.0.11
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