rider-kick 0.0.13 → 0.0.15
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 +629 -25
- 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 +236 -45
- 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 +22 -13
- 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/init_generator.rb +15 -0
- data/lib/generators/rider_kick/repositories_contract_spec.rb +95 -22
- data/lib/generators/rider_kick/scaffold_generator.rb +381 -64
- data/lib/generators/rider_kick/scaffold_generator_builder_uploaders_spec.rb +119 -14
- data/lib/generators/rider_kick/scaffold_generator_conditional_filtering_spec.rb +820 -0
- data/lib/generators/rider_kick/scaffold_generator_contracts_spec.rb +37 -10
- data/lib/generators/rider_kick/scaffold_generator_contracts_with_scope_spec.rb +42 -14
- data/lib/generators/rider_kick/scaffold_generator_engine_spec.rb +221 -0
- data/lib/generators/rider_kick/scaffold_generator_idempotent_spec.rb +38 -13
- 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 +31 -12
- data/lib/generators/rider_kick/scaffold_generator_with_scope_spec.rb +33 -12
- data/lib/generators/rider_kick/structure_generator.rb +156 -43
- 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 +3 -3
- data/lib/generators/rider_kick/structure_generator_success_spec.rb +33 -5
- 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/rider_kick.rb.tt +29 -0
- 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 +142 -66
- 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 -4
- 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 +13 -8
- 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 +3 -3
- data/lib/generators/rider_kick/templates/domains/core/utils/request_methods.rb.tt +1 -1
- 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 +3 -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/generators/rider_kick/templates/spec/support/use_case_stubber.rb +14 -0
- data/lib/rider-kick.rb +8 -6
- data/lib/rider_kick/builders/abstract_active_record_entity_builder_spec.rb +644 -0
- data/lib/rider_kick/configuration.rb +258 -0
- data/lib/rider_kick/configuration_engine_spec.rb +377 -0
- data/lib/rider_kick/entities/failure_details.rb +1 -1
- data/lib/rider_kick/entities/failure_details_spec.rb +1 -1
- data/lib/rider_kick/matchers/use_case_result.rb +1 -1
- data/lib/rider_kick/use_cases/abstract_use_case.rb +1 -1
- data/lib/rider_kick/version.rb +1 -1
- metadata +132 -8
- data/CHANGELOG.md +0 -5
|
@@ -9,7 +9,6 @@ inherit_gem: { rubocop-rails-omakase: rubocop.yml }
|
|
|
9
9
|
|
|
10
10
|
AllCops:
|
|
11
11
|
SuggestExtensions: false
|
|
12
|
-
TargetRubyVersion: 3.3.4
|
|
13
12
|
DisabledByDefault: true
|
|
14
13
|
Exclude:
|
|
15
14
|
- '**/templates/**/*'
|
|
@@ -20,8 +19,11 @@ AllCops:
|
|
|
20
19
|
- 'db/**/*'
|
|
21
20
|
- 'config/**/*'
|
|
22
21
|
- 'script/**/*'
|
|
22
|
+
- 'bin/*'
|
|
23
23
|
- 'public/views/*'
|
|
24
24
|
- 'bin/**/*'
|
|
25
|
+
- 'config/**/*'
|
|
26
|
+
- 'db/**/*'
|
|
25
27
|
- 'tmp/**/*'
|
|
26
28
|
- 'spec/spec_helper.rb'
|
|
27
29
|
- 'spec/rails_helper.rb'
|
|
@@ -1092,9 +1094,6 @@ Style/CommandLiteral:
|
|
|
1092
1094
|
Style/ConstantVisibility:
|
|
1093
1095
|
Enabled: true
|
|
1094
1096
|
|
|
1095
|
-
Style/ClassAndModuleChildren:
|
|
1096
|
-
Enabled: false
|
|
1097
|
-
|
|
1098
1097
|
Style/Documentation:
|
|
1099
1098
|
Enabled: false
|
|
1100
1099
|
|
|
@@ -1134,3 +1133,5 @@ Naming/MethodParameterName:
|
|
|
1134
1133
|
Layout/ClassStructure:
|
|
1135
1134
|
Enabled: true
|
|
1136
1135
|
|
|
1136
|
+
Style/WordArray:
|
|
1137
|
+
EnforcedStyle: brackets
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RiderKick.configure do |config|
|
|
4
|
+
# Specify the path where domain logic (entities, use cases, etc.) will be generated.
|
|
5
|
+
# Default: 'app/domains/' for main apps, 'engines/<engine_name>/app/domains/' for engines.
|
|
6
|
+
# config.domains_path = 'app/domains'
|
|
7
|
+
|
|
8
|
+
# Specify the path where models will be generated.
|
|
9
|
+
# Default: 'app/models/models' for main apps, 'engines/<engine_name>/app/models/<engine_name>/models' for engines.
|
|
10
|
+
# config.models_path = 'app/models/models'
|
|
11
|
+
|
|
12
|
+
# Specify the engine name if you are working within a Rails engine.
|
|
13
|
+
# config.engine_name = nil
|
|
14
|
+
|
|
15
|
+
# Specify a domain scope (e.g., 'admin/', 'api/v1/').
|
|
16
|
+
# config.domain_scope = ''
|
|
17
|
+
|
|
18
|
+
# Specify custom directory names for domain layers.
|
|
19
|
+
# config.use_cases_dir = 'use_cases'
|
|
20
|
+
# config.entities_dir = 'entities'
|
|
21
|
+
# config.adapters_dir = 'adapters'
|
|
22
|
+
# config.repositories_dir = 'repositories'
|
|
23
|
+
# config.builders_dir = 'builders'
|
|
24
|
+
# config.utils_dir = 'utils'
|
|
25
|
+
|
|
26
|
+
# Register custom type mappings for Dry::Types
|
|
27
|
+
# config.register_type_mapping('my_custom_type', 'Types::MyCustomType')
|
|
28
|
+
# config.register_entity_type_mapping('my_custom_type', 'Types::Strict::MyCustomType')
|
|
29
|
+
end
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
+
# RiderKick Structure Definition for <%= @scope_class %>
|
|
2
|
+
# This file acts as a centralized contract for code generation.
|
|
3
|
+
# Modifying this file and re-running 'rider_kick:scaffold' will update the domain logic.
|
|
4
|
+
|
|
1
5
|
model: <%= @model_class %>
|
|
2
6
|
resource_name: <%= @scope_path %>
|
|
3
|
-
resource_owner_id: <%= @resource_owner_id %>
|
|
4
|
-
|
|
7
|
+
resource_owner_id: <%= @resource_owner_id %> # account_id
|
|
8
|
+
resource_owner: <%= @resource_owner %> # account
|
|
9
|
+
actor: <%= @actor %> # user
|
|
10
|
+
actor_id: <%= @actor_id %> # user_id
|
|
11
|
+
scope: '' #dashboard
|
|
12
|
+
domain: '' # core
|
|
5
13
|
|
|
6
14
|
fields:
|
|
7
15
|
<% @fields.each do |f| -%>
|
|
@@ -11,122 +19,190 @@ fields:
|
|
|
11
19
|
- <%= f %>
|
|
12
20
|
<% end -%>
|
|
13
21
|
|
|
22
|
+
<% if entity_uploader_definitions.empty? -%>
|
|
23
|
+
uploaders: []
|
|
24
|
+
<% else -%>
|
|
14
25
|
uploaders:
|
|
15
|
-
<%
|
|
16
|
-
- <%=
|
|
26
|
+
<% entity_uploader_definitions.each do |uploader_hash| -%>
|
|
27
|
+
- { name: '<%= uploader_hash[:name] %>', type: '<%= uploader_hash[:type] %>' }
|
|
28
|
+
<% end -%>
|
|
17
29
|
<% end -%>
|
|
18
30
|
|
|
31
|
+
<% search_able_fields = arg_settings['search_able'].to_s.split(',').map(&:strip).reject(&:blank?) -%>
|
|
32
|
+
<% if search_able_fields.empty? -%>
|
|
33
|
+
search_able: []
|
|
34
|
+
<% else -%>
|
|
19
35
|
search_able:
|
|
20
|
-
<%
|
|
36
|
+
<% search_able_fields.each do |f| -%>
|
|
21
37
|
- <%= f %>
|
|
22
38
|
<% end -%>
|
|
39
|
+
<% end -%>
|
|
23
40
|
|
|
24
41
|
# ---- Enriched metadata (opsional, untuk tooling/insight) ----
|
|
25
42
|
schema:
|
|
26
|
-
columns:
|
|
43
|
+
columns:
|
|
44
|
+
<% if columns_meta.empty? -%>
|
|
45
|
+
[]
|
|
46
|
+
<% else -%>
|
|
27
47
|
<% columns_meta.each do |c| -%>
|
|
28
|
-
- name: <%= c[:name] %>
|
|
29
|
-
type: <%= c[:type] %>
|
|
30
|
-
sql_type: <%= c[:sql_type] %>
|
|
31
|
-
null: <%= c[:null] %>
|
|
48
|
+
- name: <%= c[:name] %>
|
|
49
|
+
type: <%= c[:type] %>
|
|
50
|
+
sql_type: <%= c[:sql_type] || 'null' %>
|
|
51
|
+
null: <%= c[:null] || 'false' %>
|
|
32
52
|
<% if c[:default].present? -%>
|
|
33
|
-
default: <%= c[:default].inspect %>
|
|
53
|
+
default: <%= c[:default].inspect %>
|
|
34
54
|
<% end -%>
|
|
35
55
|
<% if c[:precision] || c[:scale] -%>
|
|
36
|
-
precision: <%= c[:precision] || 'null' %>
|
|
37
|
-
scale: <%= c[:scale] || 'null' %>
|
|
56
|
+
precision: <%= c[:precision] || 'null' %>
|
|
57
|
+
scale: <%= c[:scale] || 'null' %>
|
|
38
58
|
<% end -%>
|
|
39
59
|
<% if c[:limit] -%>
|
|
40
|
-
limit: <%= c[:limit] %>
|
|
60
|
+
limit: <%= c[:limit] %>
|
|
41
61
|
<% end -%>
|
|
42
62
|
<% end -%>
|
|
43
|
-
|
|
63
|
+
<% end -%>
|
|
64
|
+
foreign_keys:
|
|
44
65
|
<% (fkeys_meta.presence || []).each do |fk| -%>
|
|
45
|
-
- column: <%= fk[:column] %>
|
|
46
|
-
to_table: <%= fk[:to_table] %>
|
|
66
|
+
- column: <%= fk[:column] %>
|
|
67
|
+
to_table: <%= fk[:to_table] %>
|
|
68
|
+
<% end -%>
|
|
69
|
+
<% if fkeys_meta.empty? -%>
|
|
70
|
+
[]
|
|
47
71
|
<% end -%>
|
|
48
|
-
indexes:
|
|
72
|
+
indexes:
|
|
49
73
|
<% (indexes_meta.presence || []).each do |ix| -%>
|
|
50
|
-
- columns: [<%= ix[:columns].join(', ') %>]
|
|
51
|
-
unique: <%= ix[:unique] %>
|
|
74
|
+
- columns: [<%= ix[:columns].join(', ') %>]
|
|
75
|
+
unique: <%= ix[:unique] %>
|
|
52
76
|
<% end -%>
|
|
53
|
-
|
|
77
|
+
<% if indexes_meta.empty? -%>
|
|
78
|
+
[]
|
|
79
|
+
<% end -%>
|
|
80
|
+
enums:
|
|
54
81
|
<% if enums_meta.present? -%>
|
|
55
82
|
<% enums_meta.each do |name, map| -%>
|
|
56
|
-
<%= name %>: <%= map.keys %>
|
|
83
|
+
<%= name %>: <%= map.keys %>
|
|
57
84
|
<% end -%>
|
|
58
85
|
<% else -%>
|
|
59
|
-
{}
|
|
86
|
+
{}
|
|
60
87
|
<% end -%>
|
|
61
88
|
|
|
62
89
|
controllers:
|
|
63
|
-
list_fields:
|
|
90
|
+
list_fields:
|
|
64
91
|
<% @fields.each do |f| -%>
|
|
65
|
-
- <%= f %>
|
|
92
|
+
- <%= f %>
|
|
66
93
|
<% end -%>
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
94
|
+
<% if @fields.empty? -%>
|
|
95
|
+
[]
|
|
96
|
+
<% end -%>
|
|
97
|
+
show_fields:
|
|
98
|
+
<% (@columns.map { |c| c[:name] } + @uploaders).uniq.each do |f| -%>
|
|
99
|
+
- <%= f %>
|
|
70
100
|
<% end -%>
|
|
71
|
-
|
|
101
|
+
<% if (@columns.map { |c| c[:name] } + @uploaders).uniq.empty? -%>
|
|
102
|
+
[]
|
|
103
|
+
<% end -%>
|
|
104
|
+
form_fields:
|
|
105
|
+
<% if @fields.empty? && @uploaders.empty? -%>
|
|
106
|
+
[]
|
|
107
|
+
<% else -%>
|
|
72
108
|
<% @fields.each do |f| -%>
|
|
73
|
-
|
|
74
|
-
|
|
109
|
+
<% if @uploaders.include?(f) -%>
|
|
110
|
+
- name: <%= f %>
|
|
111
|
+
type: <%= is_singular?(f) ? 'file' : 'files' %>
|
|
112
|
+
<% else -%>
|
|
113
|
+
- name: <%= f %>
|
|
114
|
+
type: <%= get_column_type(f) %>
|
|
115
|
+
<% end -%>
|
|
75
116
|
<% end -%>
|
|
76
117
|
<% @uploaders.each do |f| -%>
|
|
77
|
-
|
|
78
|
-
|
|
118
|
+
<% unless @fields.include?(f) -%>
|
|
119
|
+
- name: <%= f %>
|
|
120
|
+
type: <%= is_singular?(f) ? 'file' : 'files' %>
|
|
121
|
+
<% end -%>
|
|
122
|
+
<% end -%>
|
|
79
123
|
<% end -%>
|
|
80
124
|
|
|
81
125
|
domains:
|
|
82
|
-
action_list:
|
|
83
|
-
use_case:
|
|
84
|
-
contract:
|
|
85
|
-
<%
|
|
86
|
-
|
|
87
|
-
<%
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
126
|
+
action_list:
|
|
127
|
+
use_case:
|
|
128
|
+
contract:
|
|
129
|
+
<% if contract_lines_for_list.empty? -%>
|
|
130
|
+
[]
|
|
131
|
+
<% else -%>
|
|
132
|
+
<% contract_lines_for_list.each do |line| -%>
|
|
133
|
+
- <%= line %>
|
|
134
|
+
<% end -%>
|
|
135
|
+
<% end -%>
|
|
136
|
+
repository:
|
|
137
|
+
filters:
|
|
138
|
+
<% if repository_list_filters.empty? -%>
|
|
139
|
+
[]
|
|
140
|
+
<% else -%>
|
|
141
|
+
<% repository_list_filters.each do |line| -%>
|
|
142
|
+
- <%= line %>
|
|
143
|
+
<% end -%>
|
|
144
|
+
<% end -%>
|
|
145
|
+
|
|
146
|
+
action_fetch_by_id:
|
|
147
|
+
use_case:
|
|
148
|
+
contract:
|
|
149
|
+
- "required(:id).filled(:string)"
|
|
92
150
|
<% if @resource_owner_id.present? -%>
|
|
93
|
-
- required(:<%= @resource_owner_id %>).filled(:string)
|
|
151
|
+
- "required(:<%= @resource_owner_id %>).filled(:string)"
|
|
152
|
+
<% end -%>
|
|
153
|
+
<% search_able_fields = arg_settings['search_able'].to_s.split(',').map(&:strip).reject(&:blank?) -%>
|
|
154
|
+
<% if search_able_fields.any? -%>
|
|
155
|
+
<% search_able_fields.each do |f| -%>
|
|
156
|
+
# optional search fields: <%= f %>
|
|
157
|
+
<% end -%>
|
|
94
158
|
<% end -%>
|
|
95
159
|
|
|
96
|
-
action_create:
|
|
97
|
-
use_case:
|
|
98
|
-
contract:
|
|
160
|
+
action_create:
|
|
161
|
+
use_case:
|
|
162
|
+
contract:
|
|
99
163
|
<% if @resource_owner_id.present? -%>
|
|
100
|
-
- required(:<%= @resource_owner_id %>).filled(:string)
|
|
164
|
+
- "required(:<%= @resource_owner_id %>).filled(:string)"
|
|
101
165
|
<% end -%>
|
|
166
|
+
<% if contract_lines_for_create.empty? && !@resource_owner_id.present? -%>
|
|
167
|
+
[]
|
|
168
|
+
<% else -%>
|
|
102
169
|
<% contract_lines_for_create.each do |line| -%>
|
|
103
|
-
<%= line %>
|
|
170
|
+
- <%= line %>
|
|
171
|
+
<% end -%>
|
|
104
172
|
<% end -%>
|
|
105
173
|
|
|
106
|
-
action_update:
|
|
107
|
-
use_case:
|
|
108
|
-
contract:
|
|
109
|
-
- required(:id).filled(:string)
|
|
174
|
+
action_update:
|
|
175
|
+
use_case:
|
|
176
|
+
contract:
|
|
177
|
+
- "required(:id).filled(:string)"
|
|
110
178
|
<% if @resource_owner_id.present? -%>
|
|
111
|
-
- required(:<%= @resource_owner_id %>).filled(:string)
|
|
179
|
+
- "required(:<%= @resource_owner_id %>).filled(:string)"
|
|
112
180
|
<% end -%>
|
|
113
181
|
<% contract_lines_for_update.each do |line| -%>
|
|
114
|
-
<%= line %>
|
|
182
|
+
- <%= line %>
|
|
115
183
|
<% end -%>
|
|
116
184
|
|
|
117
|
-
action_destroy:
|
|
118
|
-
use_case:
|
|
119
|
-
contract:
|
|
120
|
-
- required(:id).filled(:string)
|
|
185
|
+
action_destroy:
|
|
186
|
+
use_case:
|
|
187
|
+
contract:
|
|
188
|
+
- "required(:id).filled(:string)"
|
|
121
189
|
<% if @resource_owner_id.present? -%>
|
|
122
|
-
- required(:<%= @resource_owner_id %>).filled(:string)
|
|
190
|
+
- "required(:<%= @resource_owner_id %>).filled(:string)"
|
|
123
191
|
<% end -%>
|
|
124
192
|
|
|
125
193
|
entity:
|
|
126
|
-
skipped_fields:
|
|
127
|
-
- id
|
|
128
|
-
- created_at
|
|
129
|
-
- updated_at
|
|
130
|
-
<% if @columns.map {
|
|
131
|
-
- type
|
|
194
|
+
skipped_fields:
|
|
195
|
+
- id
|
|
196
|
+
- created_at
|
|
197
|
+
- updated_at
|
|
198
|
+
<% if @columns.map { |c| c[:name] }.include?('type') -%>
|
|
199
|
+
- type
|
|
200
|
+
<% end -%>
|
|
201
|
+
db_attributes:
|
|
202
|
+
<% if entity_db_fields.empty? -%>
|
|
203
|
+
[]
|
|
204
|
+
<% else -%>
|
|
205
|
+
<% entity_db_fields.each do |field| -%>
|
|
206
|
+
- <%= field %>
|
|
132
207
|
<% end -%>
|
|
208
|
+
<% end -%>
|
|
@@ -1,25 +1,51 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
class
|
|
4
|
-
acts_as_builder_for_entity
|
|
3
|
+
class <%= domain_class_name %>::Builders::<%= @subject_class %> < RiderKick::Builders::AbstractActiveRecordEntityBuilder
|
|
4
|
+
acts_as_builder_for_entity <%= domain_class_name %>::Entities::<%= @subject_class%>
|
|
5
5
|
|
|
6
6
|
<% if @uploaders.present? -%>
|
|
7
7
|
def attributes_for_entity
|
|
8
8
|
{
|
|
9
|
-
<% @uploaders.each_with_index do |
|
|
10
|
-
<% if
|
|
11
|
-
<%=
|
|
9
|
+
<% @uploaders.each_with_index do |uploader, index| -%>
|
|
10
|
+
<% if uploader.type == 'single' -%>
|
|
11
|
+
<%= uploader.name %>_url: with_<%= uploader.name %>_url(@params)<%= index < @uploaders.length - 1 ? ',' : '' %>
|
|
12
12
|
<% else -%>
|
|
13
|
-
<%=
|
|
13
|
+
<%= uploader.name %>_urls: with_<%= uploader.name %>_urls(@params)<%= index < @uploaders.length - 1 ? ',' : '' %>
|
|
14
14
|
<% end -%>
|
|
15
15
|
<% end -%>
|
|
16
16
|
}
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
private
|
|
19
|
+
private
|
|
20
|
+
<% end -%>
|
|
21
|
+
<%- @uploaders.each do |uploader| -%>
|
|
22
|
+
<%- if uploader.type == 'single' -%>
|
|
23
|
+
# Metode ini akan dipanggil untuk mengisi ':<%= uploader.name %>_url'
|
|
24
|
+
def with_<%= uploader.name %>_url(model)
|
|
25
|
+
return nil unless model.<%= uploader.name %>.attached?
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
# Anda bisa mengubah logika ini, misal menggunakan Rails.application.routes.url_helpers
|
|
28
|
+
# jika Anda membutuhkan URL yang absolut.
|
|
29
|
+
model.<%= uploader.name %>.url
|
|
30
|
+
rescue StandardError
|
|
31
|
+
nil
|
|
23
32
|
end
|
|
24
|
-
|
|
33
|
+
|
|
34
|
+
<%- else -%>
|
|
35
|
+
# Metode ini akan dipanggil untuk mengisi ':<%= uploader.name %>_urls'
|
|
36
|
+
def with_<%= uploader.name %>_urls(model)
|
|
37
|
+
return [] unless model.<%= uploader.name %>.attached?
|
|
38
|
+
|
|
39
|
+
model.<%= uploader.name %>.map do |attachment|
|
|
40
|
+
# Anda bisa mengubah logika ini juga
|
|
41
|
+
attachment.url
|
|
42
|
+
rescue StandardError
|
|
43
|
+
nil
|
|
44
|
+
end.compact
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
<%- end -%>
|
|
48
|
+
<%- end -%>
|
|
49
|
+
|
|
25
50
|
end
|
|
51
|
+
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe <%= domain_class_name %>::Builders::<%= @subject_class %>, type: :builder do
|
|
6
|
+
describe '#build' do
|
|
7
|
+
let(:<%= @variable_subject %>) do
|
|
8
|
+
ClassStubber::Model.new(
|
|
9
|
+
'id' => 'test-id-123',
|
|
10
|
+
<%
|
|
11
|
+
# Get uploader field names to exclude from entity_db_fields
|
|
12
|
+
uploader_names = @uploaders.map { |u| u.name.to_s }
|
|
13
|
+
-%>
|
|
14
|
+
<% @entity_db_fields.each do |field| -%>
|
|
15
|
+
<% next if uploader_names.include?(field.to_s) -%>
|
|
16
|
+
<% column_meta = get_column_meta(field) -%>
|
|
17
|
+
<% case column_meta[:type].to_s -%>
|
|
18
|
+
<% when 'datetime', 'timestamp' -%>
|
|
19
|
+
'<%= field %>' => Time.current,
|
|
20
|
+
<% when 'date' -%>
|
|
21
|
+
'<%= field %>' => Date.current,
|
|
22
|
+
<% when 'time' -%>
|
|
23
|
+
'<%= field %>' => Time.current,
|
|
24
|
+
<% when 'boolean' -%>
|
|
25
|
+
'<%= field %>' => true,
|
|
26
|
+
<% when 'integer', 'bigint' -%>
|
|
27
|
+
'<%= field %>' => 123,
|
|
28
|
+
<% when 'decimal', 'float' -%>
|
|
29
|
+
'<%= field %>' => 123.45,
|
|
30
|
+
<% else -%>
|
|
31
|
+
'<%= field %>' => '<%= field %>_value',
|
|
32
|
+
<% end -%>
|
|
33
|
+
<% end -%>
|
|
34
|
+
<% @uploaders.each do |uploader| -%>
|
|
35
|
+
<% if uploader.type == 'single' -%>
|
|
36
|
+
'<%= uploader.name %>' => ClassStubber::ActiveStorageAttachment.new_single('http://example.com/<%= uploader.name %>.jpg'),
|
|
37
|
+
<% else -%>
|
|
38
|
+
'<%= uploader.name %>' => ClassStubber::ActiveStorageAttachment.new_multiple([
|
|
39
|
+
'http://example.com/<%= uploader.name %>_1.jpg',
|
|
40
|
+
'http://example.com/<%= uploader.name %>_2.jpg'
|
|
41
|
+
]),
|
|
42
|
+
<% end -%>
|
|
43
|
+
<% end -%>
|
|
44
|
+
'created_at' => Time.current,
|
|
45
|
+
'updated_at' => Time.current
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
let(:builder) { described_class.new(<%= @variable_subject %>) }
|
|
50
|
+
|
|
51
|
+
it 'builds entity from model' do
|
|
52
|
+
entity = builder.build
|
|
53
|
+
|
|
54
|
+
expect(entity).to be_a(<%= domain_class_name %>::Entities::<%= @subject_class %>)
|
|
55
|
+
expect(entity.id).to eq('test-id-123')
|
|
56
|
+
<% @entity_db_fields.first(2).each do |field| -%>
|
|
57
|
+
<% column_meta = get_column_meta(field) -%>
|
|
58
|
+
<% case column_meta[:type].to_s -%>
|
|
59
|
+
<% when 'datetime', 'timestamp', 'time' -%>
|
|
60
|
+
expect(entity.<%= field %>).to be_a(Time)
|
|
61
|
+
<% when 'date' -%>
|
|
62
|
+
expect(entity.<%= field %>).to be_a(Date)
|
|
63
|
+
<% when 'boolean' -%>
|
|
64
|
+
expect(entity.<%= field %>).to eq(true)
|
|
65
|
+
<% when 'integer', 'bigint' -%>
|
|
66
|
+
expect(entity.<%= field %>).to eq(123)
|
|
67
|
+
<% when 'decimal', 'float' -%>
|
|
68
|
+
expect(entity.<%= field %>).to eq(123.45)
|
|
69
|
+
<% else -%>
|
|
70
|
+
expect(entity.<%= field %>).to eq('<%= field %>_value')
|
|
71
|
+
<% end -%>
|
|
72
|
+
<% end -%>
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'includes all required entity attributes', :aggregate_failures do
|
|
76
|
+
entity = builder.build
|
|
77
|
+
|
|
78
|
+
# Entity must have these attributes (keys must exist, values can be nil for optional)
|
|
79
|
+
expect(entity).to respond_to(:id)
|
|
80
|
+
<% @entity_db_fields.each do |field| -%>
|
|
81
|
+
<% next if uploader_names.include?(field.to_s) -%>
|
|
82
|
+
expect(entity).to respond_to(:<%= field %>)
|
|
83
|
+
<% end -%>
|
|
84
|
+
<% @uploaders.each do |uploader| -%>
|
|
85
|
+
<% if uploader.type == 'single' -%>
|
|
86
|
+
expect(entity).to respond_to(:<%= uploader.name %>_url)
|
|
87
|
+
<% else -%>
|
|
88
|
+
expect(entity).to respond_to(:<%= uploader.name %>_urls)
|
|
89
|
+
<% end -%>
|
|
90
|
+
<% end -%>
|
|
91
|
+
expect(entity).to respond_to(:created_at)
|
|
92
|
+
expect(entity).to respond_to(:updated_at)
|
|
93
|
+
end
|
|
94
|
+
<% if @uploaders.present? -%>
|
|
95
|
+
|
|
96
|
+
describe '#attributes_for_entity' do
|
|
97
|
+
it 'returns hash with uploader attributes', :aggregate_failures do
|
|
98
|
+
attributes = builder.send(:attributes_for_entity)
|
|
99
|
+
|
|
100
|
+
expect(attributes).to be_a(Hash)
|
|
101
|
+
<% @uploaders.each do |uploader| -%>
|
|
102
|
+
<% if uploader.type == 'single' -%>
|
|
103
|
+
expect(attributes).to have_key(:<%= uploader.name %>_url)
|
|
104
|
+
<% else -%>
|
|
105
|
+
expect(attributes).to have_key(:<%= uploader.name %>_urls)
|
|
106
|
+
<% end -%>
|
|
107
|
+
<% end -%>
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it 'generates correct URL attributes', :aggregate_failures do
|
|
111
|
+
attributes = builder.send(:attributes_for_entity)
|
|
112
|
+
|
|
113
|
+
<% @uploaders.each do |uploader| -%>
|
|
114
|
+
<% if uploader.type == 'single' -%>
|
|
115
|
+
expect(attributes[:<%= uploader.name %>_url]).to eq('http://example.com/<%= uploader.name %>.jpg')
|
|
116
|
+
<% else -%>
|
|
117
|
+
expect(attributes[:<%= uploader.name %>_urls]).to be_an(Array)
|
|
118
|
+
expect(attributes[:<%= uploader.name %>_urls].size).to eq(2)
|
|
119
|
+
<% end -%>
|
|
120
|
+
<% end -%>
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
<% end -%>
|
|
124
|
+
|
|
125
|
+
it 'ensures all entity attributes have correct keys and types', :aggregate_failures do
|
|
126
|
+
entity = builder.build
|
|
127
|
+
entity_hash = entity.to_h
|
|
128
|
+
|
|
129
|
+
# All entity attributes must have keys in the hash (source of truth from entity)
|
|
130
|
+
expect(entity_hash).to have_key(:id)
|
|
131
|
+
expect(entity.id).to be_a(String)
|
|
132
|
+
<% @entity_db_fields.each do |field| -%>
|
|
133
|
+
<% next if uploader_names.include?(field.to_s) -%>
|
|
134
|
+
<% column_meta = get_column_meta(field) -%>
|
|
135
|
+
|
|
136
|
+
expect(entity_hash).to have_key(:<%= field %>)
|
|
137
|
+
<% case column_meta[:type].to_s -%>
|
|
138
|
+
<% when 'datetime', 'timestamp', 'time' -%>
|
|
139
|
+
expect(entity.<%= field %>).to be_a(Time) if entity.<%= field %>.present?
|
|
140
|
+
<% when 'date' -%>
|
|
141
|
+
expect(entity.<%= field %>).to be_a(Date) if entity.<%= field %>.present?
|
|
142
|
+
<% when 'boolean' -%>
|
|
143
|
+
expect([TrueClass, FalseClass, NilClass]).to include(entity.<%= field %>.class)
|
|
144
|
+
<% when 'integer', 'bigint' -%>
|
|
145
|
+
expect(entity.<%= field %>).to be_a(Integer) if entity.<%= field %>.present?
|
|
146
|
+
<% when 'decimal', 'float' -%>
|
|
147
|
+
expect(entity.<%= field %>).to be_a(Numeric) if entity.<%= field %>.present?
|
|
148
|
+
<% else -%>
|
|
149
|
+
expect(entity.<%= field %>).to be_a(String).or be_nil
|
|
150
|
+
<% end -%>
|
|
151
|
+
<% end -%>
|
|
152
|
+
<% @uploaders.each do |uploader| -%>
|
|
153
|
+
<% if uploader.type == 'single' -%>
|
|
154
|
+
|
|
155
|
+
expect(entity_hash).to have_key(:<%= uploader.name %>_url)
|
|
156
|
+
expect(entity.<%= uploader.name %>_url).to be_a(String).or be_nil
|
|
157
|
+
<% else -%>
|
|
158
|
+
|
|
159
|
+
expect(entity_hash).to have_key(:<%= uploader.name %>_urls)
|
|
160
|
+
expect(entity.<%= uploader.name %>_urls).to be_a(Array)
|
|
161
|
+
<% end -%>
|
|
162
|
+
<% end -%>
|
|
163
|
+
|
|
164
|
+
expect(entity_hash).to have_key(:created_at)
|
|
165
|
+
expect(entity.created_at).to be_a(Time) if entity.created_at.present?
|
|
166
|
+
|
|
167
|
+
expect(entity_hash).to have_key(:updated_at)
|
|
168
|
+
expect(entity.updated_at).to be_a(Time) if entity.updated_at.present?
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it 'validates entity type schema definitions', :aggregate_failures do
|
|
172
|
+
# Verify entity has correct Dry::Types definitions
|
|
173
|
+
schema = <%= domain_class_name %>::Entities::<%= @subject_class %>.schema
|
|
174
|
+
|
|
175
|
+
# ID must be required (not optional)
|
|
176
|
+
id_key = schema.key(:id)
|
|
177
|
+
expect(id_key.required?).to be true
|
|
178
|
+
# Check if type is not nilable (Constrained means not optional)
|
|
179
|
+
expect(id_key.type.to_s).to match(/Constrained|Strict/)
|
|
180
|
+
<% @entity_db_fields.each do |field| -%>
|
|
181
|
+
<% next if uploader_names.include?(field.to_s) -%>
|
|
182
|
+
<% column_meta = get_column_meta(field) -%>
|
|
183
|
+
|
|
184
|
+
# <%= field %>: <%= column_meta[:null] ? 'optional' : 'required' %>
|
|
185
|
+
<% if column_meta[:null] -%>
|
|
186
|
+
# Optional field - can be nil
|
|
187
|
+
<%= field %>_key = schema.key(:<%= field %>)
|
|
188
|
+
expect(<%= field %>_key.required?).to be false
|
|
189
|
+
<% else -%>
|
|
190
|
+
# Required field - not nilable
|
|
191
|
+
<%= field %>_key = schema.key(:<%= field %>)
|
|
192
|
+
expect(<%= field %>_key.required?).to be true
|
|
193
|
+
expect(<%= field %>_key.type.to_s).to match(/Constrained|Strict/)
|
|
194
|
+
<% end -%>
|
|
195
|
+
<% end -%>
|
|
196
|
+
<% @uploaders.each do |uploader| -%>
|
|
197
|
+
<% if uploader.type == 'single' -%>
|
|
198
|
+
|
|
199
|
+
# <%= uploader.name %>_url: optional (uploader can be nil)
|
|
200
|
+
<%= uploader.name %>_url_key = schema.key(:<%= uploader.name %>_url)
|
|
201
|
+
expect(<%= uploader.name %>_url_key.required?).to be false
|
|
202
|
+
<% else -%>
|
|
203
|
+
|
|
204
|
+
# <%= uploader.name %>_urls: required (but can be empty array)
|
|
205
|
+
<%= uploader.name %>_urls_key = schema.key(:<%= uploader.name %>_urls)
|
|
206
|
+
expect(<%= uploader.name %>_urls_key.required?).to be true
|
|
207
|
+
<% end -%>
|
|
208
|
+
<% end -%>
|
|
209
|
+
|
|
210
|
+
# Timestamps - check their actual definition
|
|
211
|
+
created_at_key = schema.key(:created_at)
|
|
212
|
+
updated_at_key = schema.key(:updated_at)
|
|
213
|
+
|
|
214
|
+
# Verify timestamps exist (they might be optional in some entities)
|
|
215
|
+
expect(schema.keys.map(&:name)).to include(:created_at, :updated_at)
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
class
|
|
4
|
-
acts_as_builder_for_entity
|
|
3
|
+
class <%= domain_class_name %>::Builders::Error < RiderKick::Builders::AbstractActiveRecordEntityBuilder
|
|
4
|
+
acts_as_builder_for_entity <%= domain_class_name %>::Entities::Error
|
|
5
5
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
class
|
|
4
|
-
acts_as_builder_for_entity
|
|
3
|
+
class <%= domain_class_name %>::Builders::Pagination < RiderKick::Builders::AbstractActiveRecordEntityBuilder
|
|
4
|
+
acts_as_builder_for_entity <%= domain_class_name %>::Entities::Pagination
|
|
5
5
|
|
|
6
6
|
def attributes_for_entity
|
|
7
7
|
{
|