k_domain 0.0.23 → 0.0.28
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.
- checksums.yaml +4 -4
- data/.builders/boot.rb +40 -0
- data/.builders/generators/configuration_generator.rb +22 -0
- data/.builders/run.rb +16 -0
- data/.github/workflows/main.yml +5 -3
- data/.gitignore +1 -0
- data/.rubocop.yml +8 -3
- data/Gemfile +2 -2
- data/k_domain.gemspec +1 -1
- data/lib/k_domain/config/_.rb +4 -0
- data/lib/k_domain/config/config.rb +19 -0
- data/lib/k_domain/config/configuration.rb +76 -0
- data/lib/k_domain/domain_model/build_rich_models.rb +83 -0
- data/lib/k_domain/domain_model/load.rb +44 -1
- data/lib/k_domain/domain_model/transform.rb +13 -11
- data/lib/k_domain/domain_model/transform_steps/step1_db_schema.rb +1 -1
- data/lib/k_domain/domain_model/transform_steps/step2_domain_models.rb +1 -1
- data/lib/k_domain/domain_model/transform_steps/step6_rails_structure_models.rb +1 -0
- data/lib/k_domain/domain_model/transform_steps/step7_rails_structure_controllers.rb +8 -3
- data/lib/k_domain/domain_model/transform_steps/step8_domain_columns.rb +51 -56
- data/lib/k_domain/queries/_.rb +4 -0
- data/lib/k_domain/queries/base_query.rb +13 -0
- data/lib/k_domain/queries/domain_model_query.rb +88 -0
- data/lib/k_domain/rails_code_extractor/extract_controller.rb +2 -0
- data/lib/k_domain/rails_code_extractor/extract_model.rb +2 -0
- data/lib/k_domain/rails_code_extractor/shim_loader.rb +4 -2
- data/lib/k_domain/raw_db_schema/transform.rb +26 -2
- data/lib/k_domain/schemas/_.rb +3 -1
- data/lib/k_domain/schemas/domain/erd_file.rb +78 -77
- data/lib/k_domain/schemas/domain.rb +79 -38
- data/lib/k_domain/schemas/{domain/_.rb → domain_types.rb} +1 -8
- data/lib/k_domain/schemas/{domain_model.rb → main_dataset.rb} +2 -2
- data/lib/k_domain/schemas/rails_structure.rb +10 -0
- data/lib/k_domain/version.rb +1 -1
- data/lib/k_domain.rb +6 -1
- data/templates/custom/action_controller.rb +0 -29
- data/templates/custom/controller_interceptors.rb +9 -7
- data/templates/custom/model_interceptors.rb +48 -3
- data/templates/rails/active_record.rb +2 -0
- data/templates/sample_config.rb +47 -0
- metadata +17 -10
- data/.builders/config/_.rb +0 -3
- data/.builders/setup.rb +0 -30
- data/templates/old_printspeek_schema copy.rb +0 -231
- data/templates/old_printspeek_schema.rb +0 -233
@@ -9,15 +9,15 @@ class Step8DomainColumns < KDomain::DomainModel::Step
|
|
9
9
|
attr_reader :column_symbol
|
10
10
|
|
11
11
|
def call
|
12
|
+
@debug = true
|
12
13
|
enrich_columns
|
13
14
|
end
|
14
15
|
|
15
16
|
def enrich_columns
|
16
17
|
# .select {|m| m[:name] == 'app_user'}
|
17
18
|
domain_models.each do |model|
|
18
|
-
@domain_model = model
|
19
|
+
@domain_model = enrich_model(model)
|
19
20
|
# this will be nil if there is no rails model code
|
20
|
-
@rails_model = find_rails_structure_models(domain_model[:name])
|
21
21
|
|
22
22
|
# log.warn domain_model[:name]
|
23
23
|
domain_model[:columns].each do |column|
|
@@ -25,75 +25,29 @@ class Step8DomainColumns < KDomain::DomainModel::Step
|
|
25
25
|
@column_name = column[:name]
|
26
26
|
@column_symbol = column[:name].to_sym
|
27
27
|
|
28
|
-
attach_foreign_key
|
29
28
|
column[:structure_type] = structure_type
|
30
29
|
end
|
31
30
|
end
|
32
31
|
end
|
33
32
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
# is_foreign = foreign_key?(column_name)
|
38
|
-
structure_type = structure_type(is_foreign)
|
39
|
-
|
40
|
-
column.merge({
|
41
|
-
structure_type: structure_type,
|
42
|
-
foreign_key: is_foreign,
|
43
|
-
foreign_table: (foreign_table || '').singularize,
|
44
|
-
foreign_table_plural: (foreign_table || '').pluralize
|
45
|
-
})
|
46
|
-
end
|
47
|
-
|
48
|
-
def lookup_foreign_table(column_name)
|
49
|
-
foreign_table = find_foreign_table(table[:name], column_name)
|
50
|
-
|
51
|
-
return foreign_table if foreign_table
|
52
|
-
|
53
|
-
cn = column_name.to_s
|
54
|
-
|
55
|
-
if cn.ends_with?('_id')
|
56
|
-
table_name = column_name[0..-4]
|
57
|
-
table_name_plural = table_name.pluralize
|
58
|
-
|
59
|
-
if table_name_exist?(table_name_plural.to_s)
|
60
|
-
investigate(step: :step8_columns,
|
61
|
-
location: :lookup_foreign_table,
|
62
|
-
key: column_name,
|
63
|
-
message: "#{@table[:name]}.#{column_name} => #{table_name_plural} - Relationship not found in DB, so have inferred this relationship. You may want to check that this relation is correct")
|
64
|
-
|
65
|
-
return table_name
|
66
|
-
end
|
67
|
-
|
68
|
-
investigate(step: :step8_columns,
|
69
|
-
location: :lookup_foreign_table,
|
70
|
-
key: column_name,
|
71
|
-
message: "#{@table[:name]}.#{column_name} => #{table_name_plural} - Table not found for a column that looks like foreign_key")
|
72
|
-
end
|
73
|
-
|
74
|
-
nil
|
75
|
-
end
|
33
|
+
def enrich_model(model)
|
34
|
+
# NOTE: THIS MAY GET MOVED TO DomainModel::Load#enrichment
|
35
|
+
@rails_model = find_rails_structure_models(model[:name])
|
76
36
|
|
77
|
-
|
78
|
-
return if rails_model.nil? || rails_model[:behaviours].nil? || rails_model[:behaviours][:belongs_to].nil?
|
37
|
+
model[:file] = @rails_model[:file]
|
79
38
|
|
80
|
-
|
39
|
+
log.error "Rails model not found for: #{model[:name]}" unless @rails_model
|
81
40
|
|
82
|
-
|
83
|
-
|
84
|
-
# NEED TO PRE-LOAD the table, table_plural and model
|
85
|
-
domain_column[:foreign_table] = 'xxx1'
|
86
|
-
domain_column[:foreign_table_plural] = 'xxx3'
|
87
|
-
domain_column[:foreign_model] = 'xxx2'
|
41
|
+
model
|
88
42
|
end
|
89
43
|
|
90
44
|
# Need some configurable data dictionary where by
|
91
45
|
# _token can be setup on a project by project basis
|
92
46
|
def structure_type
|
93
47
|
return :primary_key if domain_model[:pk][:name] == column_name
|
94
|
-
return :foreign_key if
|
48
|
+
return :foreign_key if foreign_relationship?
|
49
|
+
return :foreign_type if column_symbol == :context_type || column_symbol == :element_type
|
95
50
|
|
96
|
-
return :timestamp if column_symbol == :created_at || column_symbol == :updated_at
|
97
51
|
return :timestamp if column_symbol == :created_at || column_symbol == :updated_at
|
98
52
|
return :deleted_at if column_symbol == :deleted_at
|
99
53
|
return :encrypted_password if column_symbol == :encrypted_password
|
@@ -101,4 +55,45 @@ class Step8DomainColumns < KDomain::DomainModel::Step
|
|
101
55
|
|
102
56
|
:data
|
103
57
|
end
|
58
|
+
|
59
|
+
def foreign_relationship?
|
60
|
+
return false if rails_model.nil? || rails_model[:behaviours].nil? || rails_model[:behaviours][:belongs_to].nil?
|
61
|
+
|
62
|
+
column_name = domain_column[:name].to_sym
|
63
|
+
rails_model[:behaviours][:belongs_to].any? { |belong| belong[:opts][:foreign_key].to_sym == column_name }
|
64
|
+
end
|
65
|
+
|
66
|
+
# def attach_relationships
|
67
|
+
# domain_column[:relationships] = []
|
68
|
+
# return if rails_model.nil? || rails_model[:behaviours].nil? || rails_model[:behaviours][:belongs_to].nil?
|
69
|
+
|
70
|
+
# column_name = domain_column[:name].to_sym
|
71
|
+
|
72
|
+
# attach_column_relationships(column_name)
|
73
|
+
# end
|
74
|
+
|
75
|
+
# def select_belongs_to(column_name)
|
76
|
+
# rails_model[:behaviours][:belongs_to].select { |belong| belong[:opts][:foreign_key].to_sym == column_name.to_sym }
|
77
|
+
# end
|
78
|
+
|
79
|
+
# # this just maps basic relationship information,
|
80
|
+
# # to go deeper you really need to use the Rails Model Behaviours
|
81
|
+
# def attach_column_relationships(column_name)
|
82
|
+
# select_belongs_to(column_name).each do |belongs_to|
|
83
|
+
# domain_column[:relationships] << map_belongs_to(belongs_to)
|
84
|
+
# end
|
85
|
+
# end
|
86
|
+
|
87
|
+
# def map_belongs_to(belongs_to)
|
88
|
+
# @domain_column[:structure_type] = :foreign_key
|
89
|
+
# # result = {
|
90
|
+
# # type: :belongs_to,
|
91
|
+
# # name: belongs_to[:name],
|
92
|
+
# # foreign_key: belongs_to.dig(:opts, :foreign_key) || @domain_column[:name],
|
93
|
+
# # }
|
94
|
+
|
95
|
+
# # result[:primary_key] = belongs_to.dig(:opts, :primary_key) if belongs_to.dig(:opts, :primary_key)
|
96
|
+
# # result[:class_name] = belongs_to.dig(:opts, :class_name) if belongs_to.dig(:opts, :class_name)
|
97
|
+
# result
|
98
|
+
# end
|
104
99
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KDomain
|
4
|
+
module Queries
|
5
|
+
# Query models found on the domain model
|
6
|
+
# by
|
7
|
+
# has ruby file
|
8
|
+
# has primary key
|
9
|
+
# column count
|
10
|
+
# data column count
|
11
|
+
# foreign key column count
|
12
|
+
# has timestamp (created_at, updated_at) columns
|
13
|
+
# has created_at
|
14
|
+
# has updated_at
|
15
|
+
# has deleted_at
|
16
|
+
# has polymorphic foreign keys
|
17
|
+
# has virtual columns
|
18
|
+
# virtual column filters (token, encrypted_password, etc)
|
19
|
+
class DomainModelQuery < BaseQuery
|
20
|
+
def all
|
21
|
+
domain_model.domain.models
|
22
|
+
end
|
23
|
+
|
24
|
+
def query(**filters)
|
25
|
+
@query = all.clone
|
26
|
+
|
27
|
+
filters.each do |key, value|
|
28
|
+
send("filter_#{key}", value)
|
29
|
+
end
|
30
|
+
|
31
|
+
@query
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def filter_ruby(value)
|
37
|
+
@query.select! { |model| model.ruby? == value }
|
38
|
+
end
|
39
|
+
|
40
|
+
def filter_pk(value)
|
41
|
+
@query.select! { |model| model.pk.exist? == value }
|
42
|
+
end
|
43
|
+
|
44
|
+
def filter_column_count(block)
|
45
|
+
@query.select! { |model| block.call(model.columns.count) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def filter_data_column_count(block)
|
49
|
+
@query.select! { |model| block.call(model.columns_data.count) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def filter_foreign_key_column_count(block)
|
53
|
+
@query.select! { |model| block.call(model.columns_foreign_key.count) }
|
54
|
+
end
|
55
|
+
alias filter_fk_column_count filter_foreign_key_column_count
|
56
|
+
alias filter_fk_count filter_foreign_key_column_count
|
57
|
+
|
58
|
+
def filter_polymorphic_foreign_key_column_count(block)
|
59
|
+
@query.select! { |model| block.call(model.columns_foreign_type.count) }
|
60
|
+
end
|
61
|
+
alias filter_poly_fk_column_count filter_polymorphic_foreign_key_column_count
|
62
|
+
alias filter_poly_fk_count filter_polymorphic_foreign_key_column_count
|
63
|
+
|
64
|
+
def filter_timestamp(value)
|
65
|
+
@query.select! { |model| (model.columns_timestamp.count == 2) == value }
|
66
|
+
end
|
67
|
+
|
68
|
+
def filter_created_at(value)
|
69
|
+
@query.select! { |model| (model.columns.any? { |column| column.name == 'created_at' } == value) }
|
70
|
+
end
|
71
|
+
|
72
|
+
def filter_updated_at(value)
|
73
|
+
@query.select! { |model| (model.columns.any? { |column| column.name == 'updated_at' } == value) }
|
74
|
+
end
|
75
|
+
|
76
|
+
def filter_deleted_at(value)
|
77
|
+
@query.select! { |model| (model.columns.any? { |column| column.name == 'deleted_at' } == value) }
|
78
|
+
end
|
79
|
+
# has virtual columns
|
80
|
+
# virtual column filters (token, encrypted_password, etc)
|
81
|
+
|
82
|
+
# # HELP: this filter affects table rows, eg. if a table has less the 2 columns then include the table
|
83
|
+
# low_column: -> (model) { model.columns.length < 5 },
|
84
|
+
# suspected_m2m: -> (model) { model.columns_foreign.length == 2 && model.columns_data.length < 3 },
|
85
|
+
# invalid_types: -> (model) { model.columns.any? { |c| [c.db_type, c.csharp_type, c.ruby_type].include?('******') } },
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -48,9 +48,11 @@ module KDomain
|
|
48
48
|
# puts e.message
|
49
49
|
if e.is_a?(NameError) && e.message != last_error&.message
|
50
50
|
log.kv('add module', e.name)
|
51
|
+
log.kv 'file', file
|
51
52
|
eval("module #{e.name}; end")
|
52
53
|
return load_retry(file, times - 1, e)
|
53
54
|
end
|
55
|
+
log.kv 'file', file
|
54
56
|
log.exception(e, style: :short, method_info: method(__callee__))
|
55
57
|
end
|
56
58
|
# rubocop:enable Security/Eval,Style/EvalWithLocation,Style/DocumentDynamicEvalDefinition,Metrics/AbcSize
|
@@ -58,9 +58,11 @@ module KDomain
|
|
58
58
|
# puts e.message
|
59
59
|
if e.is_a?(NameError) && e.message != last_error&.message
|
60
60
|
log.kv('add module', e.name)
|
61
|
+
log.kv 'file', file
|
61
62
|
eval("module #{e.name}; end")
|
62
63
|
return load_retry(file, times - 1, e)
|
63
64
|
end
|
65
|
+
log.kv 'file', file
|
64
66
|
log.exception(e, style: :short, method_info: method(__callee__))
|
65
67
|
end
|
66
68
|
# rubocop:enable Security/Eval,Style/EvalWithLocation,Style/DocumentDynamicEvalDefinition,Metrics/AbcSize
|
@@ -18,8 +18,10 @@ module KDomain
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def call
|
21
|
-
|
22
|
-
|
21
|
+
shim_files.select { |sf| sf[:exist] }.each do |sf|
|
22
|
+
require sf[:file]
|
23
|
+
end
|
24
|
+
nil
|
23
25
|
end
|
24
26
|
|
25
27
|
def register(name, file)
|
@@ -7,16 +7,29 @@
|
|
7
7
|
# builds the hash
|
8
8
|
module KDomain
|
9
9
|
module RawDbSchema
|
10
|
+
# class TransformFilter
|
11
|
+
# attr_accessor :take
|
12
|
+
# def initialize(take: :all)
|
13
|
+
# @take = take
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
|
10
17
|
class Transform
|
11
18
|
include KLog::Logging
|
12
19
|
|
13
20
|
attr_reader :source_file
|
14
21
|
attr_accessor :template_file
|
15
22
|
attr_reader :schema_loader
|
23
|
+
attr_reader :filter
|
16
24
|
|
17
|
-
|
25
|
+
# @param [String] source_file Rails Schema file
|
26
|
+
# @param [OpenStruct] filter Settings for filtering data before transformation, this is useful during debugging
|
27
|
+
# examples
|
28
|
+
# filter = os(run: 1, tables: os(offset: 10, limit: 10))
|
29
|
+
def initialize(source_file, filter)
|
18
30
|
@source_file = source_file
|
19
31
|
@template_file = KDomain::Gem.resource('templates/load_schema.rb')
|
32
|
+
@filter = filter
|
20
33
|
end
|
21
34
|
|
22
35
|
def call
|
@@ -73,11 +86,22 @@ module KDomain
|
|
73
86
|
|
74
87
|
loader = LoadSchema.new
|
75
88
|
loader.load_schema
|
76
|
-
|
89
|
+
|
90
|
+
apply_filter(loader.schema)
|
77
91
|
rescue StandardError => e
|
78
92
|
log.exception(e)
|
79
93
|
end
|
80
94
|
# rubocop:enable Security/Eval
|
95
|
+
|
96
|
+
# rubocop:disable Metrics/AbcSize
|
97
|
+
def apply_filter(schema)
|
98
|
+
return schema unless filter.active == 1
|
99
|
+
|
100
|
+
schema[:tables] = schema[:tables].slice(filter.table.offset, filter.table.limit) || [] if filter.table.offset.is_a?(Integer) && filter.table.limit.is_a?(Integer)
|
101
|
+
|
102
|
+
schema
|
103
|
+
end
|
104
|
+
# rubocop:enable Metrics/AbcSize
|
81
105
|
end
|
82
106
|
end
|
83
107
|
end
|
data/lib/k_domain/schemas/_.rb
CHANGED
@@ -11,6 +11,8 @@ require_relative 'rails_structure'
|
|
11
11
|
require_relative 'investigate'
|
12
12
|
require_relative 'database'
|
13
13
|
require_relative 'dictionary'
|
14
|
+
require_relative 'domain_types'
|
14
15
|
require_relative 'domain'
|
16
|
+
require_relative 'main_dataset'
|
15
17
|
|
16
|
-
require_relative './domain_model'
|
18
|
+
# require_relative './domain_model'
|
@@ -1,82 +1,83 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
# # frozen_string_literal: true
|
2
3
|
|
3
|
-
# Domain class holds a list of the entities
|
4
|
-
module KDomain
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
# # Domain class holds a list of the entities
|
5
|
+
# module KDomain
|
6
|
+
# module DomainModel
|
7
|
+
#
|
8
|
+
# class ErdFile < Dry::Struct
|
9
|
+
# attribute :name , Types::Strict::String
|
10
|
+
# attribute :name_plural , Types::Strict::String
|
11
|
+
# attribute :dsl_file , Types::Strict::String
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
# attribute? :source , Dry::Struct.optional.default(nil) do
|
14
|
+
# attribute :ruby , Types::Strict::String
|
15
|
+
# attribute :public , Types::Strict::String.optional.default(nil)
|
16
|
+
# attribute :private , Types::Strict::String.optional.default(nil)
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
18
|
+
# attribute? :all_methods , Dry::Struct.optional.default(nil) do
|
19
|
+
# attribute? :klass , Types::Strict::Array do
|
20
|
+
# attribute :name , Types::Strict::String
|
21
|
+
# attribute :scope , Types::Strict::String # .optional.default(nil)
|
22
|
+
# attribute :class_method , Types::Strict::Bool
|
23
|
+
# attribute :arguments , Types::Strict::String
|
24
|
+
# end
|
25
|
+
# attribute? :instance , Types::Strict::Array do
|
26
|
+
# attribute :name , Types::Strict::String
|
27
|
+
# attribute :scope , Types::Strict::String # .optional.default(nil)
|
28
|
+
# attribute :class_method , Types::Strict::Bool
|
29
|
+
# attribute :arguments , Types::Strict::String
|
30
|
+
# end
|
31
|
+
# attribute? :instance_public , Types::Strict::Array do
|
32
|
+
# attribute :name , Types::Strict::String
|
33
|
+
# attribute :scope , Types::Strict::String # .optional.default(nil)
|
34
|
+
# attribute :class_method , Types::Strict::Bool
|
35
|
+
# attribute :arguments , Types::Strict::String
|
36
|
+
# end
|
37
|
+
# attribute? :instance_private , Types::Strict::Array do
|
38
|
+
# attribute :name , Types::Strict::String
|
39
|
+
# attribute :scope , Types::Strict::String # .optional.default(nil)
|
40
|
+
# attribute :class_method , Types::Strict::Bool
|
41
|
+
# attribute :arguments , Types::Strict::String
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
# attribute? :dsl , Dry::Struct.optional.default(nil) do
|
46
|
+
# attribute :default_scope , Types::Strict::String.optional.default(nil)
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
48
|
+
# attribute? :scopes , Types::Strict::Array do
|
49
|
+
# attribute :name , Types::Strict::String
|
50
|
+
# attribute :scope , Types::Strict::String # .optional.default(nil)
|
51
|
+
# end
|
52
|
+
# attribute? :belongs_to , Types::Strict::Array do
|
53
|
+
# attribute :name , Types::Strict::String
|
54
|
+
# attribute :options , Types::Strict::Hash.optional.default({}.freeze)
|
55
|
+
# attribute :raw_options , Types::Strict::String
|
56
|
+
# end
|
57
|
+
# attribute? :has_one , Types::Strict::Array do
|
58
|
+
# attribute :name , Types::Strict::String
|
59
|
+
# attribute :options , Types::Strict::Hash.optional.default({}.freeze)
|
60
|
+
# attribute :raw_options , Types::Strict::String
|
61
|
+
# end
|
62
|
+
# attribute? :has_many , Types::Strict::Array do
|
63
|
+
# attribute :name , Types::Strict::String
|
64
|
+
# attribute :options , Types::Strict::Hash.optional.default({}.freeze)
|
65
|
+
# attribute :raw_options , Types::Strict::String
|
66
|
+
# end
|
67
|
+
# attribute? :has_and_belongs_to_many , Types::Strict::Array do
|
68
|
+
# attribute :name , Types::Strict::String
|
69
|
+
# attribute :options , Types::Strict::Hash.optional.default({}.freeze)
|
70
|
+
# attribute :raw_options , Types::Strict::String
|
71
|
+
# end
|
72
|
+
# attribute? :validate_on , Types::Strict::Array do
|
73
|
+
# attribute :line , Types::Strict::String
|
74
|
+
# end
|
75
|
+
# attribute? :validates_on , Types::Strict::Array do
|
76
|
+
# attribute :name , Types::Strict::String
|
77
|
+
# attribute :raw_options , Types::Strict::String
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
# # rubocop:enable Metrics/BlockLength
|
82
|
+
# end
|
83
|
+
# end
|