rider-kick 0.0.12 → 0.0.14
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/README.md +668 -27
- data/lib/generators/rider_kick/USAGE +2 -0
- data/lib/generators/rider_kick/base_generator.rb +190 -0
- data/lib/generators/rider_kick/clean_arch_generator.rb +235 -44
- data/lib/generators/rider_kick/clean_arch_generator_engine_spec.rb +359 -0
- data/lib/generators/rider_kick/clean_arch_generator_factory_bot_spec.rb +131 -0
- data/lib/generators/rider_kick/entity_type_mapping_spec.rb +61 -0
- data/lib/generators/rider_kick/errors.rb +42 -0
- data/lib/generators/rider_kick/factory_generator.rb +238 -0
- data/lib/generators/rider_kick/factory_generator_spec.rb +175 -0
- data/lib/generators/rider_kick/repositories_contract_spec.rb +135 -0
- data/lib/generators/rider_kick/scaffold_generator.rb +377 -62
- data/lib/generators/rider_kick/scaffold_generator_builder_uploaders_spec.rb +159 -0
- data/lib/generators/rider_kick/scaffold_generator_conditional_filtering_spec.rb +820 -0
- data/lib/generators/rider_kick/scaffold_generator_contracts_spec.rb +96 -0
- data/lib/generators/rider_kick/scaffold_generator_contracts_with_scope_spec.rb +83 -0
- data/lib/generators/rider_kick/scaffold_generator_engine_spec.rb +221 -0
- data/lib/generators/rider_kick/scaffold_generator_idempotent_spec.rb +84 -0
- data/lib/generators/rider_kick/scaffold_generator_list_spec_format_spec.rb +153 -0
- data/lib/generators/rider_kick/scaffold_generator_rspec_spec.rb +347 -0
- data/lib/generators/rider_kick/scaffold_generator_success_spec.rb +101 -0
- data/lib/generators/rider_kick/scaffold_generator_with_scope_spec.rb +76 -0
- data/lib/generators/rider_kick/structure_generator.rb +179 -35
- data/lib/generators/rider_kick/structure_generator_comprehensive_spec.rb +598 -0
- data/lib/generators/rider_kick/structure_generator_engine_spec.rb +279 -0
- data/lib/generators/rider_kick/structure_generator_spec.rb +20 -0
- data/lib/generators/rider_kick/structure_generator_success_spec.rb +64 -0
- data/lib/generators/rider_kick/structure_generator_unit_spec.rb +2202 -0
- data/lib/generators/rider_kick/templates/.rubocop.yml +5 -4
- data/lib/generators/rider_kick/templates/config/initializers/version.rb.tt +1 -1
- data/lib/generators/rider_kick/templates/db/migrate/20220613145533_init_database.rb +1 -1
- data/lib/generators/rider_kick/templates/db/structures/example.yaml.tt +157 -51
- data/lib/generators/rider_kick/templates/domains/core/builders/builder.rb.tt +36 -10
- data/lib/generators/rider_kick/templates/domains/core/builders/builder_spec.rb.tt +219 -0
- data/lib/generators/rider_kick/templates/domains/core/builders/error.rb.tt +2 -2
- data/lib/generators/rider_kick/templates/domains/core/builders/pagination.rb.tt +2 -2
- data/lib/generators/rider_kick/templates/domains/core/entities/entity.rb.tt +32 -14
- data/lib/generators/rider_kick/templates/domains/core/entities/error.rb.tt +1 -1
- data/lib/generators/rider_kick/templates/domains/core/entities/pagination.rb.tt +1 -1
- data/lib/generators/rider_kick/templates/domains/core/repositories/abstract_repository.rb.tt +4 -16
- data/lib/generators/rider_kick/templates/domains/core/repositories/create.rb.tt +2 -2
- data/lib/generators/rider_kick/templates/domains/core/repositories/create_spec.rb.tt +78 -0
- data/lib/generators/rider_kick/templates/domains/core/repositories/destroy.rb.tt +2 -2
- data/lib/generators/rider_kick/templates/domains/core/repositories/destroy_spec.rb.tt +88 -0
- data/lib/generators/rider_kick/templates/domains/core/repositories/fetch_by_id.rb.tt +3 -3
- data/lib/generators/rider_kick/templates/domains/core/repositories/fetch_by_id_spec.rb.tt +62 -0
- data/lib/generators/rider_kick/templates/domains/core/repositories/list.rb.tt +12 -7
- data/lib/generators/rider_kick/templates/domains/core/repositories/list_spec.rb.tt +190 -0
- data/lib/generators/rider_kick/templates/domains/core/repositories/update.rb.tt +4 -4
- data/lib/generators/rider_kick/templates/domains/core/repositories/update_spec.rb.tt +119 -0
- data/lib/generators/rider_kick/templates/domains/core/use_cases/contract/default.rb.tt +1 -1
- data/lib/generators/rider_kick/templates/domains/core/use_cases/contract/pagination.rb.tt +1 -1
- data/lib/generators/rider_kick/templates/domains/core/use_cases/create.rb.tt +3 -7
- data/lib/generators/rider_kick/templates/domains/core/use_cases/create_spec.rb.tt +71 -0
- data/lib/generators/rider_kick/templates/domains/core/use_cases/destroy.rb.tt +3 -7
- data/lib/generators/rider_kick/templates/domains/core/use_cases/destroy_spec.rb.tt +62 -0
- data/lib/generators/rider_kick/templates/domains/core/use_cases/fetch_by_id.rb.tt +3 -7
- data/lib/generators/rider_kick/templates/domains/core/use_cases/fetch_by_id_spec.rb.tt +62 -0
- data/lib/generators/rider_kick/templates/domains/core/use_cases/get_version.rb.tt +2 -2
- data/lib/generators/rider_kick/templates/domains/core/use_cases/list.rb.tt +3 -7
- data/lib/generators/rider_kick/templates/domains/core/use_cases/list_spec.rb.tt +64 -0
- data/lib/generators/rider_kick/templates/domains/core/use_cases/update.rb.tt +3 -7
- data/lib/generators/rider_kick/templates/domains/core/use_cases/update_spec.rb.tt +73 -0
- data/lib/generators/rider_kick/templates/domains/core/utils/abstract_utils.rb.tt +29 -0
- data/lib/generators/rider_kick/templates/domains/core/utils/request_methods.rb.tt +3 -2
- data/lib/generators/rider_kick/templates/env.development +1 -1
- data/lib/generators/rider_kick/templates/env.production +1 -1
- data/lib/generators/rider_kick/templates/env.test +1 -1
- data/lib/generators/rider_kick/templates/models/{application_record.rb → application_record.rb.tt} +3 -1
- data/lib/generators/rider_kick/templates/models/model_spec.rb.tt +68 -0
- data/lib/generators/rider_kick/templates/spec/factories/.gitkeep +19 -0
- data/lib/generators/rider_kick/templates/spec/factories/factory.rb.tt +8 -0
- data/lib/generators/rider_kick/templates/spec/rails_helper.rb +2 -0
- data/lib/generators/rider_kick/templates/spec/support/class_stubber.rb +148 -0
- data/lib/generators/rider_kick/templates/spec/support/factory_bot.rb +34 -0
- data/lib/generators/rider_kick/templates/spec/support/faker.rb +61 -0
- data/lib/rider-kick.rb +9 -6
- data/lib/rider_kick/builders/abstract_active_record_entity_builder_spec.rb +596 -68
- data/lib/rider_kick/configuration.rb +238 -0
- data/lib/rider_kick/configuration_engine_spec.rb +377 -0
- data/lib/rider_kick/entities/failure_details.rb +23 -15
- data/lib/rider_kick/entities/failure_details_spec.rb +22 -0
- data/lib/rider_kick/matchers/use_case_result.rb +1 -1
- data/lib/rider_kick/matchers/use_case_result_edge_spec.rb +28 -0
- data/lib/rider_kick/use_cases/abstract_use_case.rb +1 -1
- data/lib/rider_kick/use_cases/abstract_use_case_spec.rb +57 -0
- data/lib/rider_kick/version.rb +1 -1
- metadata +345 -52
- data/.rspec +0 -3
- data/.rubocop.yml +0 -1141
- data/CHANGELOG.md +0 -5
- data/Rakefile +0 -12
- data/lib/rider_kick/matchers/use_case_result_spec.rb +0 -64
|
@@ -1,11 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
require 'active_support/inflector'
|
|
5
|
+
require 'active_support/core_ext/object/blank'
|
|
6
|
+
require 'active_support/core_ext/enumerable'
|
|
7
|
+
require 'hashie'
|
|
8
|
+
require_relative 'base_generator'
|
|
9
|
+
require_relative '../../rider-kick'
|
|
10
|
+
|
|
1
11
|
module RiderKick
|
|
2
|
-
class Structure <
|
|
12
|
+
class Structure < BaseGenerator
|
|
3
13
|
source_root File.expand_path('templates', __dir__)
|
|
4
14
|
|
|
5
15
|
argument :arg_model_name, type: :string, default: '', banner: 'Models::Name'
|
|
6
|
-
argument :arg_settings, type: :hash, default:
|
|
16
|
+
argument :arg_settings, type: :hash, default: {}, banner: 'route_scope:dashboard actor:user uploaders:assets,images,picture,document'
|
|
17
|
+
class_option :engine, type: :string, default: nil, desc: 'Specify engine name (e.g., Core, Admin)'
|
|
18
|
+
class_option :domain, type: :string, default: '', desc: 'Specify domain scope (e.g., core/, admin/, api/v1/)'
|
|
7
19
|
|
|
8
20
|
def generate_use_case
|
|
21
|
+
configure_engine
|
|
9
22
|
validation!
|
|
10
23
|
setup_variables
|
|
11
24
|
generate_files(@scope_path)
|
|
@@ -14,45 +27,161 @@ module RiderKick
|
|
|
14
27
|
private
|
|
15
28
|
|
|
16
29
|
def validation!
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
30
|
+
validate_domains_path!
|
|
31
|
+
|
|
32
|
+
# Pastikan parameter wajib tersedia
|
|
33
|
+
actor = arg_settings['actor'].to_s.strip
|
|
34
|
+
resource_owner = arg_settings['resource_owner'].to_s.strip
|
|
35
|
+
resource_owner_id = arg_settings['resource_owner_id'].to_s.strip
|
|
36
|
+
|
|
37
|
+
if actor.blank?
|
|
38
|
+
raise ValidationError.new(
|
|
39
|
+
"Missing required setting: actor. Contoh: 'actor:user'",
|
|
40
|
+
setting: 'actor',
|
|
41
|
+
provided_settings: arg_settings.keys
|
|
42
|
+
)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
if resource_owner.blank?
|
|
46
|
+
raise ValidationError.new(
|
|
47
|
+
"Missing required setting: resource_owner. Contoh: 'resource_owner:account'",
|
|
48
|
+
setting: 'resource_owner',
|
|
49
|
+
provided_settings: arg_settings.keys
|
|
50
|
+
)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
if resource_owner_id.blank?
|
|
54
|
+
raise ValidationError.new(
|
|
55
|
+
"Missing required setting: resource_owner_id. Contoh: 'resource_owner_id:account_id'",
|
|
56
|
+
setting: 'resource_owner_id',
|
|
57
|
+
provided_settings: arg_settings.keys
|
|
58
|
+
)
|
|
20
59
|
end
|
|
21
60
|
end
|
|
22
61
|
|
|
23
62
|
def setup_variables
|
|
24
|
-
@variable_subject
|
|
63
|
+
@variable_subject = arg_model_name.split('::').last.underscore.downcase
|
|
64
|
+
validate_model_exists!(arg_model_name.camelize)
|
|
25
65
|
@model_class = arg_model_name.camelize.constantize
|
|
26
66
|
@subject_class = arg_model_name.split('::').last
|
|
27
67
|
@scope_path = @subject_class.pluralize.underscore.downcase
|
|
28
68
|
@scope_class = @scope_path.camelize
|
|
29
69
|
@fields = contract_fields
|
|
30
|
-
@uploaders = uploaders
|
|
31
|
-
@actor = arg_settings['actor'].downcase
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
'
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
70
|
+
@uploaders = uploaders # Ini array string dari argumen
|
|
71
|
+
@actor = arg_settings['actor'].to_s.downcase
|
|
72
|
+
@actor_id = (@actor.present? ? arg_settings['actor'].to_s.downcase + '_id' : '')
|
|
73
|
+
|
|
74
|
+
@resource_owner = arg_settings['resource_owner'].to_s.presence
|
|
75
|
+
@resource_owner_id = arg_settings['resource_owner_id'].to_s.presence
|
|
76
|
+
@columns = columns_meta
|
|
77
|
+
|
|
78
|
+
@type_mapping = RiderKick.configuration.type_mapping
|
|
79
|
+
@entity_type_mapping = RiderKick.configuration.entity_type_mapping
|
|
80
|
+
|
|
81
|
+
@columns_meta_hash = @columns.index_by { |c| c[:name] }
|
|
82
|
+
|
|
83
|
+
@contract_lines_for_create = @fields.map do |field_name|
|
|
84
|
+
column_meta = @columns_meta_hash[field_name]
|
|
85
|
+
next nil if column_meta.nil?
|
|
86
|
+
|
|
87
|
+
predicate = column_meta[:null] ? 'optional' : 'required'
|
|
88
|
+
db_type = get_column_type(field_name).to_s
|
|
89
|
+
validation_type = @type_mapping[db_type]
|
|
90
|
+
|
|
91
|
+
if db_type == 'upload'
|
|
92
|
+
validation_type = 'Types::File'
|
|
93
|
+
elsif validation_type.nil?
|
|
94
|
+
validation_type = ':string'
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
if predicate == 'required'
|
|
98
|
+
"\"required(:#{field_name}).filled(#{validation_type})\""
|
|
99
|
+
else
|
|
100
|
+
"\"optional(:#{field_name}).maybe(#{validation_type})\""
|
|
101
|
+
end
|
|
102
|
+
end.compact
|
|
103
|
+
|
|
104
|
+
@contract_lines_for_update = @fields.map do |field_name|
|
|
105
|
+
column_meta = @columns_meta_hash[field_name]
|
|
106
|
+
next nil if column_meta.nil?
|
|
107
|
+
|
|
108
|
+
db_type = get_column_type(field_name).to_s
|
|
109
|
+
validation_type = @type_mapping[db_type]
|
|
110
|
+
|
|
111
|
+
if db_type == 'upload'
|
|
112
|
+
validation_type = 'Types::File'
|
|
113
|
+
elsif validation_type.nil?
|
|
114
|
+
validation_type = ':string'
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
"\"optional(:#{field_name}).maybe(#{validation_type})\""
|
|
118
|
+
end.compact
|
|
119
|
+
|
|
120
|
+
search_able_fields = arg_settings['search_able'].to_s.split(',').map(&:strip).reject(&:blank?)
|
|
121
|
+
|
|
122
|
+
@repository_list_filters = search_able_fields.map do |field|
|
|
123
|
+
"{ field: '#{field}', type: 'search' }"
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
@contract_lines_for_list = @repository_list_filters.map do |filter_hash|
|
|
127
|
+
field_name = filter_hash.match(/field: '([^']+)'/)[1]
|
|
128
|
+
"\"optional(:#{field_name}).maybe(:string)\""
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
@entity_db_fields = @fields
|
|
132
|
+
|
|
133
|
+
# 1. Tentukan definisi uploader yang kaya (array of hashes)
|
|
134
|
+
# @uploaders di sini masih array string dari argumen
|
|
135
|
+
@entity_uploader_definitions = @uploaders.map do |uploader_name|
|
|
136
|
+
type = is_singular?(uploader_name) ? 'single' : 'multiple'
|
|
137
|
+
# PERBAIKAN: Ini harus menjadi Hash, BUKAN String
|
|
138
|
+
{ name: uploader_name, type: type }
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def columns_meta
|
|
143
|
+
@model_class.columns.map do |c|
|
|
144
|
+
{
|
|
145
|
+
name: c.name.to_s,
|
|
146
|
+
type: c.type,
|
|
147
|
+
sql_type: (c.respond_to?(:sql_type) ? c.sql_type : nil),
|
|
148
|
+
null: (c.respond_to?(:null) ? c.null : nil),
|
|
149
|
+
default: (c.respond_to?(:default) ? c.default : nil),
|
|
150
|
+
precision: (c.respond_to?(:precision) ? c.precision : nil),
|
|
151
|
+
scale: (c.respond_to?(:scale) ? c.scale : nil),
|
|
152
|
+
limit: (c.respond_to?(:limit) ? c.limit : nil)
|
|
153
|
+
}
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def fkeys_meta = []
|
|
158
|
+
|
|
159
|
+
def indexes_meta = []
|
|
160
|
+
|
|
161
|
+
def enums_meta = {}
|
|
162
|
+
|
|
163
|
+
def contract_lines_for_create
|
|
164
|
+
@contract_lines_for_create || []
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def contract_lines_for_update
|
|
168
|
+
@contract_lines_for_update || []
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def contract_lines_for_list
|
|
172
|
+
@contract_lines_for_list || []
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def repository_list_filters
|
|
176
|
+
@repository_list_filters || []
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def entity_db_fields
|
|
180
|
+
@entity_db_fields || []
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def entity_uploader_definitions
|
|
184
|
+
@entity_uploader_definitions || []
|
|
56
185
|
end
|
|
57
186
|
|
|
58
187
|
def is_singular?(str)
|
|
@@ -60,18 +189,33 @@ module RiderKick
|
|
|
60
189
|
end
|
|
61
190
|
|
|
62
191
|
def generate_files(action)
|
|
63
|
-
|
|
192
|
+
structure_path = if RiderKick.configuration.engine_name.present?
|
|
193
|
+
# For engines, generate structure file in engine's db/structures directory
|
|
194
|
+
engine_name = RiderKick.configuration.engine_name.downcase
|
|
195
|
+
"engines/#{engine_name}/db/structures/#{action}_structure.yaml"
|
|
196
|
+
else
|
|
197
|
+
# For main app, generate in host's db/structures directory
|
|
198
|
+
"db/structures/#{action}_structure.yaml"
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
template 'db/structures/example.yaml.tt', structure_path
|
|
64
202
|
end
|
|
65
203
|
|
|
66
204
|
def contract_fields
|
|
67
|
-
|
|
205
|
+
# Metode ini sekarang hanya digunakan oleh setup_variables untuk @fields
|
|
206
|
+
@model_class.columns.reject { |column|
|
|
207
|
+
(uploaders + ['id', 'created_at', 'updated_at', 'type']).include?(column.name.to_s)
|
|
208
|
+
}.map(&:name).map(&:to_s)
|
|
68
209
|
end
|
|
69
210
|
|
|
70
211
|
def get_column_type(field)
|
|
71
|
-
uploaders
|
|
212
|
+
# uploaders di sini masih array string
|
|
213
|
+
uploaders.include?(field) ?
|
|
214
|
+
'upload' : @model_class.columns_hash[field].type
|
|
72
215
|
end
|
|
73
216
|
|
|
74
217
|
def uploaders
|
|
218
|
+
# Ini adalah array string mentah dari argumen
|
|
75
219
|
return [] unless arg_settings['uploaders'].present?
|
|
76
220
|
arg_settings['uploaders'].split(',').map(&:strip)
|
|
77
221
|
end
|