rider-kick 0.0.13 → 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 +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 +235 -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/repositories_contract_spec.rb +95 -22
- data/lib/generators/rider_kick/scaffold_generator.rb +377 -62
- 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 +40 -11
- 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 +32 -11
- data/lib/generators/rider_kick/structure_generator.rb +154 -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/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 +140 -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 +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 +8 -6
- data/lib/rider_kick/builders/abstract_active_record_entity_builder_spec.rb +644 -0
- 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 +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 +129 -8
- data/CHANGELOG.md +0 -5
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_support/inflector'
|
|
4
|
+
|
|
5
|
+
module RiderKick
|
|
6
|
+
DEFAULT_TYPE_MAPPING = {
|
|
7
|
+
'uuid' => ':string',
|
|
8
|
+
'string' => ':string',
|
|
9
|
+
'text' => ':string',
|
|
10
|
+
'integer' => ':integer',
|
|
11
|
+
'boolean' => ':bool',
|
|
12
|
+
'float' => ':float',
|
|
13
|
+
'decimal' => ':decimal',
|
|
14
|
+
'date' => ':date',
|
|
15
|
+
'upload' => 'Types::File',
|
|
16
|
+
'datetime' => ':time'
|
|
17
|
+
}.freeze
|
|
18
|
+
public_constant :DEFAULT_TYPE_MAPPING
|
|
19
|
+
|
|
20
|
+
DEFAULT_ENTITY_TYPE_MAPPING = {
|
|
21
|
+
'uuid' => 'Types::Strict::String',
|
|
22
|
+
'string' => 'Types::Strict::String',
|
|
23
|
+
'text' => 'Types::Strict::String',
|
|
24
|
+
'integer' => 'Types::Strict::Integer',
|
|
25
|
+
'boolean' => 'Types::Strict::Bool',
|
|
26
|
+
'float' => 'Types::Strict::Float',
|
|
27
|
+
'decimal' => 'Types::Strict::Decimal',
|
|
28
|
+
'date' => 'Types::Strict::Date',
|
|
29
|
+
'datetime' => 'Types::Strict::Time'
|
|
30
|
+
}.freeze
|
|
31
|
+
public_constant :DEFAULT_ENTITY_TYPE_MAPPING
|
|
32
|
+
# Backward compatibility constants
|
|
33
|
+
TYPE_MAPPING = DEFAULT_TYPE_MAPPING
|
|
34
|
+
ENTITY_TYPE_MAPPING = DEFAULT_ENTITY_TYPE_MAPPING
|
|
35
|
+
public_constant :TYPE_MAPPING
|
|
36
|
+
public_constant :ENTITY_TYPE_MAPPING
|
|
37
|
+
|
|
38
|
+
# Faker mapping registry for factory generator customization
|
|
39
|
+
class FakerMapping
|
|
40
|
+
@mappings = {}
|
|
41
|
+
|
|
42
|
+
class << self
|
|
43
|
+
attr_reader :mappings
|
|
44
|
+
|
|
45
|
+
def register(expression, &block)
|
|
46
|
+
@mappings[expression] = block
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def get(expression)
|
|
50
|
+
@mappings[expression]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def clear
|
|
54
|
+
@mappings = {}
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class Configuration
|
|
60
|
+
attr_reader :domains_path, :models_path, :engine_name, :domain_scope, :template_path
|
|
61
|
+
attr_accessor :entities_path, :adapters_path
|
|
62
|
+
|
|
63
|
+
def initialize
|
|
64
|
+
@engine_name = detect_engine_name
|
|
65
|
+
@domain_scope = ''
|
|
66
|
+
@domains_path = detect_domains_path
|
|
67
|
+
@entities_path = File.join(@domains_path, 'entities')
|
|
68
|
+
@adapters_path = File.join(@domains_path, 'adapters')
|
|
69
|
+
@models_path = detect_models_path
|
|
70
|
+
@template_path = nil
|
|
71
|
+
@type_mapping = DEFAULT_TYPE_MAPPING.dup
|
|
72
|
+
@entity_type_mapping = DEFAULT_ENTITY_TYPE_MAPPING.dup
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
attr_reader :type_mapping
|
|
76
|
+
|
|
77
|
+
attr_reader :entity_type_mapping
|
|
78
|
+
|
|
79
|
+
def register_type_mapping(db_type, dry_type)
|
|
80
|
+
@type_mapping[db_type.to_s] = dry_type.to_s
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def register_entity_type_mapping(db_type, dry_type)
|
|
84
|
+
@entity_type_mapping[db_type.to_s] = dry_type.to_s
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def domains_path=(path)
|
|
88
|
+
validate_path_format!(path, 'domains_path')
|
|
89
|
+
@domains_path = File.expand_path(path)
|
|
90
|
+
@entities_path = File.join(@domains_path, 'entities')
|
|
91
|
+
@adapters_path = File.join(@domains_path, 'adapters')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def models_path=(path)
|
|
95
|
+
validate_path_format!(path, 'models_path')
|
|
96
|
+
@models_path = File.expand_path(path)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def template_path=(path)
|
|
100
|
+
if path.nil? || path.to_s.strip.empty?
|
|
101
|
+
@template_path = nil
|
|
102
|
+
else
|
|
103
|
+
validate_path_format!(path, 'template_path')
|
|
104
|
+
@template_path = File.expand_path(path)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def engine_name=(name)
|
|
109
|
+
if name.nil? || name.to_s.strip.empty?
|
|
110
|
+
@engine_name = nil
|
|
111
|
+
else
|
|
112
|
+
validate_engine_name_format!(name)
|
|
113
|
+
@engine_name = name.to_s
|
|
114
|
+
end
|
|
115
|
+
@models_path = detect_models_path
|
|
116
|
+
@domains_path = detect_domains_path
|
|
117
|
+
@entities_path = File.join(@domains_path, 'entities')
|
|
118
|
+
@adapters_path = File.join(@domains_path, 'adapters')
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def domain_scope=(scope)
|
|
122
|
+
if scope.nil? || scope.to_s.strip.empty?
|
|
123
|
+
@domain_scope = ''
|
|
124
|
+
else
|
|
125
|
+
validate_domain_scope_format!(scope)
|
|
126
|
+
@domain_scope = scope.to_s
|
|
127
|
+
end
|
|
128
|
+
@domains_path = detect_domains_path
|
|
129
|
+
@entities_path = File.join(@domains_path, 'entities')
|
|
130
|
+
@adapters_path = File.join(@domains_path, 'adapters')
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
private
|
|
134
|
+
|
|
135
|
+
def validate_path_format!(path, attribute_name)
|
|
136
|
+
path_str = path.to_s.strip
|
|
137
|
+
return if path_str.empty?
|
|
138
|
+
|
|
139
|
+
# Basic path validation - should not contain invalid characters
|
|
140
|
+
if path_str.match?(/[<>:"|?*\x00-\x1f]/)
|
|
141
|
+
raise RiderKick::ConfigurationError.new(
|
|
142
|
+
"Invalid #{attribute_name} format: contains invalid characters",
|
|
143
|
+
attribute: attribute_name,
|
|
144
|
+
value: path_str
|
|
145
|
+
)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def validate_engine_name_format!(name)
|
|
150
|
+
name_str = name.to_s.strip
|
|
151
|
+
return if name_str.empty?
|
|
152
|
+
|
|
153
|
+
# Engine name can be CamelCase (e.g., 'Core', 'Admin') or underscore_case (e.g., 'order_engine')
|
|
154
|
+
# Both formats are acceptable and will be converted as needed
|
|
155
|
+
unless name_str.match?(/^[A-Z][a-zA-Z0-9]*$/) || name_str.match?(/^[a-z][a-z0-9_]*$/)
|
|
156
|
+
raise RiderKick::ConfigurationError.new(
|
|
157
|
+
"Invalid engine_name format: must be CamelCase (e.g., 'Core', 'Admin') or underscore_case (e.g., 'order_engine')",
|
|
158
|
+
attribute: 'engine_name',
|
|
159
|
+
value: name_str,
|
|
160
|
+
suggestion: "Use CamelCase format like 'Core' or 'Admin', or underscore_case like 'order_engine'"
|
|
161
|
+
)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def validate_domain_scope_format!(scope)
|
|
166
|
+
scope_str = scope.to_s.strip
|
|
167
|
+
return if scope_str.empty?
|
|
168
|
+
|
|
169
|
+
# Domain scope should contain only alphanumeric, slash, underscore, hyphen
|
|
170
|
+
unless scope_str.match?(/^[a-zA-Z0-9\/_-]+$/)
|
|
171
|
+
raise RiderKick::ConfigurationError.new(
|
|
172
|
+
'Invalid domain_scope format: must contain only alphanumeric characters, slashes, underscores, and hyphens',
|
|
173
|
+
attribute: 'domain_scope',
|
|
174
|
+
value: scope_str,
|
|
175
|
+
suggestion: "Use format like 'core/', 'admin/', 'api/v1/'"
|
|
176
|
+
)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def detect_engine_name
|
|
181
|
+
# Detect engine dari struktur file system
|
|
182
|
+
# Cek apakah ada lib/<name>/engine.rb
|
|
183
|
+
return nil unless Dir.exist?('lib')
|
|
184
|
+
|
|
185
|
+
engines = []
|
|
186
|
+
Dir.glob('lib/*/engine.rb').each do |engine_file|
|
|
187
|
+
engine_name = File.basename(File.dirname(engine_file))
|
|
188
|
+
engines << engine_name.camelize if File.exist?(engine_file)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Jika hanya ada satu engine, return itu
|
|
192
|
+
return engines.first if engines.length == 1
|
|
193
|
+
|
|
194
|
+
# Jika ada multiple engines, return nil (user harus specify via --engine option)
|
|
195
|
+
# Atau cek dari gem name di gemspec (fallback)
|
|
196
|
+
gemspec_files = Dir.glob('*.gemspec')
|
|
197
|
+
unless gemspec_files.empty?
|
|
198
|
+
gemspec_content = File.read(gemspec_files.first)
|
|
199
|
+
if gemspec_content =~ /\.name\s*=\s*["']([^"']+)["']/
|
|
200
|
+
gem_name = Regexp.last_match(1)
|
|
201
|
+
# Extract engine name dari gem name (e.g., "my_app-core" -> "Core")
|
|
202
|
+
engine_name = gem_name.split(/[-_]/).last.camelize
|
|
203
|
+
return engine_name if Dir.exist?("lib/#{engine_name.underscore}") && engines.include?(engine_name)
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
nil
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def detect_models_path
|
|
211
|
+
if @engine_name
|
|
212
|
+
# Engine: engines/<engine_name>/app/models/<engine_name>/models
|
|
213
|
+
File.join('engines', @engine_name.underscore, 'app/models', @engine_name.underscore, 'models')
|
|
214
|
+
else
|
|
215
|
+
# Main app: app/models/models
|
|
216
|
+
'app/models/models'
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def detect_domains_path
|
|
221
|
+
if @engine_name
|
|
222
|
+
# Engine: engines/<engine_name>/app/domains/<domain_scope>
|
|
223
|
+
File.join('engines', @engine_name.underscore, 'app/domains', @domain_scope)
|
|
224
|
+
else
|
|
225
|
+
# Main app: app/domains/<domain_scope>
|
|
226
|
+
File.join('app/domains', @domain_scope)
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def self.configuration
|
|
232
|
+
@configuration ||= Configuration.new
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def self.configure
|
|
236
|
+
yield(configuration)
|
|
237
|
+
end
|
|
238
|
+
end
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'tmpdir'
|
|
4
|
+
require 'fileutils'
|
|
5
|
+
require 'rider_kick/configuration'
|
|
6
|
+
|
|
7
|
+
RSpec.describe RiderKick::Configuration do
|
|
8
|
+
describe '#engine_name detection' do
|
|
9
|
+
it 'returns nil when no engine found' do
|
|
10
|
+
Dir.mktmpdir do |dir|
|
|
11
|
+
Dir.chdir(dir) do
|
|
12
|
+
FileUtils.mkdir_p('lib')
|
|
13
|
+
config = RiderKick::Configuration.new
|
|
14
|
+
expect(config.engine_name).to be_nil
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'returns engine name when single engine found' do
|
|
20
|
+
Dir.mktmpdir do |dir|
|
|
21
|
+
Dir.chdir(dir) do
|
|
22
|
+
FileUtils.mkdir_p('lib/core')
|
|
23
|
+
File.write('lib/core/engine.rb', 'module Core; class Engine < ::Rails::Engine; end; end')
|
|
24
|
+
|
|
25
|
+
config = RiderKick::Configuration.new
|
|
26
|
+
expect(config.engine_name).to eq('Core')
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'returns nil when multiple engines found (requires explicit specification)' do
|
|
32
|
+
Dir.mktmpdir do |dir|
|
|
33
|
+
Dir.chdir(dir) do
|
|
34
|
+
FileUtils.mkdir_p(['lib/core', 'lib/admin'])
|
|
35
|
+
File.write('lib/core/engine.rb', 'module Core; class Engine < ::Rails::Engine; end; end')
|
|
36
|
+
File.write('lib/admin/engine.rb', 'module Admin; class Engine < ::Rails::Engine; end; end')
|
|
37
|
+
|
|
38
|
+
config = RiderKick::Configuration.new
|
|
39
|
+
expect(config.engine_name).to be_nil
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'can be set explicitly via engine_name=' do
|
|
45
|
+
Dir.mktmpdir do |dir|
|
|
46
|
+
Dir.chdir(dir) do
|
|
47
|
+
config = RiderKick::Configuration.new
|
|
48
|
+
config.engine_name = 'Core'
|
|
49
|
+
expect(config.engine_name).to eq('Core')
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'sets engine_name to nil when given nil' do
|
|
55
|
+
Dir.mktmpdir do |dir|
|
|
56
|
+
Dir.chdir(dir) do
|
|
57
|
+
config = RiderKick::Configuration.new
|
|
58
|
+
config.engine_name = 'Core'
|
|
59
|
+
config.engine_name = nil
|
|
60
|
+
expect(config.engine_name).to be_nil
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'sets engine_name to nil when given empty string' do
|
|
66
|
+
Dir.mktmpdir do |dir|
|
|
67
|
+
Dir.chdir(dir) do
|
|
68
|
+
config = RiderKick::Configuration.new
|
|
69
|
+
config.engine_name = ''
|
|
70
|
+
expect(config.engine_name).to be_nil
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe '#models_path' do
|
|
77
|
+
it 'returns app/models/models when no engine' do
|
|
78
|
+
Dir.mktmpdir do |dir|
|
|
79
|
+
Dir.chdir(dir) do
|
|
80
|
+
config = RiderKick::Configuration.new
|
|
81
|
+
config.engine_name = nil
|
|
82
|
+
expect(config.models_path).to eq('app/models/models')
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'returns engines/<engine_name>/app/models/<engine_name>/models when engine is set' do
|
|
88
|
+
Dir.mktmpdir do |dir|
|
|
89
|
+
Dir.chdir(dir) do
|
|
90
|
+
config = RiderKick::Configuration.new
|
|
91
|
+
config.engine_name = 'Core'
|
|
92
|
+
expect(config.models_path).to eq('engines/core/app/models/core/models')
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it 'updates models_path when engine_name changes' do
|
|
98
|
+
Dir.mktmpdir do |dir|
|
|
99
|
+
Dir.chdir(dir) do
|
|
100
|
+
config = RiderKick::Configuration.new
|
|
101
|
+
|
|
102
|
+
config.engine_name = nil
|
|
103
|
+
expect(config.models_path).to eq('app/models/models')
|
|
104
|
+
|
|
105
|
+
config.engine_name = 'Admin'
|
|
106
|
+
expect(config.models_path).to eq('engines/admin/app/models/admin/models')
|
|
107
|
+
|
|
108
|
+
config.engine_name = nil
|
|
109
|
+
expect(config.models_path).to eq('app/models/models')
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
describe '#detect_engine_name' do
|
|
116
|
+
it 'returns nil when lib directory does not exist' do
|
|
117
|
+
Dir.mktmpdir do |dir|
|
|
118
|
+
Dir.chdir(dir) do
|
|
119
|
+
config = RiderKick::Configuration.new
|
|
120
|
+
expect(config.engine_name).to be_nil
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it 'detects engine from gemspec fallback when multiple engines exist' do
|
|
126
|
+
Dir.mktmpdir do |dir|
|
|
127
|
+
Dir.chdir(dir) do
|
|
128
|
+
FileUtils.mkdir_p(['lib/core', 'lib/admin'])
|
|
129
|
+
File.write('lib/core/engine.rb', 'module Core; class Engine < ::Rails::Engine; end; end')
|
|
130
|
+
File.write('lib/admin/engine.rb', 'module Admin; class Engine < ::Rails::Engine; end; end')
|
|
131
|
+
File.write('test-admin.gemspec', "Gem::Specification.new do |s|\n s.name = 'test-admin'\nend")
|
|
132
|
+
|
|
133
|
+
config = RiderKick::Configuration.new
|
|
134
|
+
# Should return Admin because gemspec name matches Admin engine
|
|
135
|
+
# The logic checks if gemspec name matches an existing engine
|
|
136
|
+
expect(config.engine_name).to eq('Admin')
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it 'detects engine from gemspec fallback when single matching engine' do
|
|
142
|
+
Dir.mktmpdir do |dir|
|
|
143
|
+
Dir.chdir(dir) do
|
|
144
|
+
FileUtils.mkdir_p('lib/core')
|
|
145
|
+
File.write('lib/core/engine.rb', 'module Core; class Engine < ::Rails::Engine; end; end')
|
|
146
|
+
File.write('test-core.gemspec', "Gem::Specification.new do |s|\n s.name = 'test-core'\nend")
|
|
147
|
+
|
|
148
|
+
config = RiderKick::Configuration.new
|
|
149
|
+
# Should return Core because it matches the gemspec name
|
|
150
|
+
expect(config.engine_name).to eq('Core')
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
describe '#detect_domains_path' do
|
|
157
|
+
it 'returns app/domains/<domain_scope> when no engine' do
|
|
158
|
+
Dir.mktmpdir do |dir|
|
|
159
|
+
Dir.chdir(dir) do
|
|
160
|
+
config = RiderKick::Configuration.new
|
|
161
|
+
config.engine_name = nil
|
|
162
|
+
config.domain_scope = 'admin/'
|
|
163
|
+
expect(config.domains_path).to eq('app/domains/admin/')
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it 'returns engines/<engine_name>/app/domains/<domain_scope> when engine is set' do
|
|
169
|
+
Dir.mktmpdir do |dir|
|
|
170
|
+
Dir.chdir(dir) do
|
|
171
|
+
config = RiderKick::Configuration.new
|
|
172
|
+
config.engine_name = 'Core'
|
|
173
|
+
config.domain_scope = 'admin/'
|
|
174
|
+
expect(config.domains_path).to eq('engines/core/app/domains/admin/')
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it 'handles empty domain_scope' do
|
|
180
|
+
Dir.mktmpdir do |dir|
|
|
181
|
+
Dir.chdir(dir) do
|
|
182
|
+
config = RiderKick::Configuration.new
|
|
183
|
+
config.engine_name = nil
|
|
184
|
+
config.domain_scope = ''
|
|
185
|
+
expect(config.domains_path).to eq('app/domains/')
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
describe '#domains_path=' do
|
|
192
|
+
it 'updates @domains_path with expanded path' do
|
|
193
|
+
Dir.mktmpdir do |dir|
|
|
194
|
+
Dir.chdir(dir) do
|
|
195
|
+
config = RiderKick::Configuration.new
|
|
196
|
+
config.domains_path = 'custom/path'
|
|
197
|
+
expect(config.domains_path).to eq(File.expand_path('custom/path'))
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
it 'updates @entities_path' do
|
|
203
|
+
Dir.mktmpdir do |dir|
|
|
204
|
+
Dir.chdir(dir) do
|
|
205
|
+
config = RiderKick::Configuration.new
|
|
206
|
+
config.domains_path = 'custom/path'
|
|
207
|
+
expect(config.entities_path).to eq(File.join(File.expand_path('custom/path'), 'entities'))
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
it 'updates @adapters_path' do
|
|
213
|
+
Dir.mktmpdir do |dir|
|
|
214
|
+
Dir.chdir(dir) do
|
|
215
|
+
config = RiderKick::Configuration.new
|
|
216
|
+
config.domains_path = 'custom/path'
|
|
217
|
+
expect(config.adapters_path).to eq(File.join(File.expand_path('custom/path'), 'adapters'))
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
describe '#models_path=' do
|
|
224
|
+
it 'updates @models_path with expanded path' do
|
|
225
|
+
Dir.mktmpdir do |dir|
|
|
226
|
+
Dir.chdir(dir) do
|
|
227
|
+
config = RiderKick::Configuration.new
|
|
228
|
+
config.models_path = 'custom/models'
|
|
229
|
+
expect(config.models_path).to eq(File.expand_path('custom/models'))
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
describe '#engine_name=' do
|
|
236
|
+
it 'updates paths when engine_name is set' do
|
|
237
|
+
Dir.mktmpdir do |dir|
|
|
238
|
+
Dir.chdir(dir) do
|
|
239
|
+
config = RiderKick::Configuration.new
|
|
240
|
+
config.engine_name = 'Core'
|
|
241
|
+
expect(config.models_path).to eq('engines/core/app/models/core/models')
|
|
242
|
+
expect(config.domains_path).to eq('engines/core/app/domains/')
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
it 'updates entities_path and adapters_path when engine_name is set' do
|
|
248
|
+
Dir.mktmpdir do |dir|
|
|
249
|
+
Dir.chdir(dir) do
|
|
250
|
+
config = RiderKick::Configuration.new
|
|
251
|
+
config.engine_name = 'Core'
|
|
252
|
+
expect(config.entities_path).to eq('engines/core/app/domains/entities')
|
|
253
|
+
expect(config.adapters_path).to eq('engines/core/app/domains/adapters')
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
it 'handles nil' do
|
|
259
|
+
Dir.mktmpdir do |dir|
|
|
260
|
+
Dir.chdir(dir) do
|
|
261
|
+
config = RiderKick::Configuration.new
|
|
262
|
+
config.engine_name = 'Core'
|
|
263
|
+
config.engine_name = nil
|
|
264
|
+
expect(config.engine_name).to be_nil
|
|
265
|
+
expect(config.models_path).to eq('app/models/models')
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
it 'handles empty string' do
|
|
271
|
+
Dir.mktmpdir do |dir|
|
|
272
|
+
Dir.chdir(dir) do
|
|
273
|
+
config = RiderKick::Configuration.new
|
|
274
|
+
config.engine_name = 'Core'
|
|
275
|
+
config.engine_name = ''
|
|
276
|
+
expect(config.engine_name).to be_nil
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
it 'handles whitespace-only string' do
|
|
282
|
+
Dir.mktmpdir do |dir|
|
|
283
|
+
Dir.chdir(dir) do
|
|
284
|
+
config = RiderKick::Configuration.new
|
|
285
|
+
config.engine_name = ' '
|
|
286
|
+
expect(config.engine_name).to be_nil
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
describe '#domain_scope=' do
|
|
293
|
+
it 'updates domains_path when domain_scope is set' do
|
|
294
|
+
Dir.mktmpdir do |dir|
|
|
295
|
+
Dir.chdir(dir) do
|
|
296
|
+
config = RiderKick::Configuration.new
|
|
297
|
+
config.domain_scope = 'admin/'
|
|
298
|
+
expect(config.domains_path).to eq('app/domains/admin/')
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
it 'updates entities_path and adapters_path when domain_scope is set' do
|
|
304
|
+
Dir.mktmpdir do |dir|
|
|
305
|
+
Dir.chdir(dir) do
|
|
306
|
+
config = RiderKick::Configuration.new
|
|
307
|
+
config.domain_scope = 'admin/'
|
|
308
|
+
expect(config.entities_path).to eq('app/domains/admin/entities')
|
|
309
|
+
expect(config.adapters_path).to eq('app/domains/admin/adapters')
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
it 'handles nil' do
|
|
315
|
+
Dir.mktmpdir do |dir|
|
|
316
|
+
Dir.chdir(dir) do
|
|
317
|
+
config = RiderKick::Configuration.new
|
|
318
|
+
config.domain_scope = 'admin/'
|
|
319
|
+
config.domain_scope = nil
|
|
320
|
+
expect(config.domain_scope).to eq('')
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
it 'handles empty string' do
|
|
326
|
+
Dir.mktmpdir do |dir|
|
|
327
|
+
Dir.chdir(dir) do
|
|
328
|
+
config = RiderKick::Configuration.new
|
|
329
|
+
config.domain_scope = 'admin/'
|
|
330
|
+
config.domain_scope = ''
|
|
331
|
+
expect(config.domain_scope).to eq('')
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
it 'handles whitespace-only string' do
|
|
337
|
+
Dir.mktmpdir do |dir|
|
|
338
|
+
Dir.chdir(dir) do
|
|
339
|
+
config = RiderKick::Configuration.new
|
|
340
|
+
config.domain_scope = ' '
|
|
341
|
+
expect(config.domain_scope).to eq('')
|
|
342
|
+
end
|
|
343
|
+
end
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
it 'updates paths correctly with engine and domain_scope' do
|
|
347
|
+
Dir.mktmpdir do |dir|
|
|
348
|
+
Dir.chdir(dir) do
|
|
349
|
+
config = RiderKick::Configuration.new
|
|
350
|
+
config.engine_name = 'Core'
|
|
351
|
+
config.domain_scope = 'admin/'
|
|
352
|
+
expect(config.domains_path).to eq('engines/core/app/domains/admin/')
|
|
353
|
+
expect(config.entities_path).to eq('engines/core/app/domains/admin/entities')
|
|
354
|
+
expect(config.adapters_path).to eq('engines/core/app/domains/admin/adapters')
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
describe 'RiderKick.configuration' do
|
|
361
|
+
it 'returns singleton Configuration instance' do
|
|
362
|
+
config1 = RiderKick.configuration
|
|
363
|
+
config2 = RiderKick.configuration
|
|
364
|
+
expect(config1.object_id).to eq(config2.object_id)
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
describe 'RiderKick.configure' do
|
|
369
|
+
it 'yields configuration instance' do
|
|
370
|
+
RiderKick.configure do |config|
|
|
371
|
+
expect(config).to be_a(RiderKick::Configuration)
|
|
372
|
+
config.engine_name = 'TestEngine'
|
|
373
|
+
expect(config.engine_name).to eq('TestEngine')
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
RSpec.describe RiderKick::Entities::FailureDetails do
|
|
4
4
|
it 'from_array menggabungkan pesan secara dinamis' do
|
|
5
|
-
fd = described_class.from_array(
|
|
5
|
+
fd = described_class.from_array(['alpha', 'beta', 'gamma'])
|
|
6
6
|
expect(fd.message).to eq('alpha, beta, gamma')
|
|
7
7
|
expect(fd.type).to eq(:error)
|
|
8
8
|
expect(fd.other_properties).to eq({})
|