rage_arch 0.1.2 → 0.1.4
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 +158 -5
- data/lib/generators/rage_arch/ar_dep_generator.rb +1 -1
- data/lib/generators/rage_arch/dep_switch_generator.rb +16 -16
- data/lib/generators/rage_arch/install_generator.rb +1 -1
- data/lib/generators/rage_arch/scaffold_generator.rb +2 -2
- data/lib/generators/rage_arch/templates/scaffold/post_repo.rb.tt +1 -1
- data/lib/rage_arch/container.rb +1 -1
- data/lib/rage_arch/dep_scanner.rb +1 -1
- data/lib/rage_arch/deps/active_record.rb +1 -1
- data/lib/rage_arch/event_publisher.rb +1 -1
- data/lib/rage_arch/fake_event_publisher.rb +1 -1
- data/lib/rage_arch/railtie.rb +4 -4
- data/lib/rage_arch/rspec_matchers.rb +1 -1
- data/lib/rage_arch/use_case.rb +3 -3
- data/lib/rage_arch/version.rb +1 -1
- data/lib/rage_arch.rb +2 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 152d8ad4517ebc11b70103f2dadbc68d14363d66e93c83ed8513755b7f4d3faa
|
|
4
|
+
data.tar.gz: 5c15a711f1676d67644a75a66f7a7731504f56bc76ef75d1a2f420f4d900dae6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bb854fce9230a8e3dc7efbec5257ca1ea9f98d91bb417262d4fe3d3a014d1e47df337acffb93eea453f438d2c525f92c06d003b1e2eabc63f99d95af3a10e3bf
|
|
7
|
+
data.tar.gz: b350e0aa5995ac0b63a30a8ade4ab78314b1755f56884998622434b585fa1f5b7bf16ade394666706b6569561ea256c1be74386f8b711232ab73c16dd8982947
|
data/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# RageArch
|
|
2
2
|
|
|
3
3
|
**Clean Architecture Light for Rails.** Business logic in testable use cases, thin controllers, and models free of callbacks.
|
|
4
4
|
|
|
@@ -58,18 +58,120 @@ use_case = RageArch::UseCase::Base.build(:create_order)
|
|
|
58
58
|
result = use_case.call(reference: "REF-1", total_cents: 1000)
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
+
#### `ar_dep` — inline ActiveRecord dep
|
|
62
|
+
|
|
63
|
+
When a dep is a simple wrapper over an ActiveRecord model, declare it directly in the use case instead of creating a separate class:
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
class Posts::Create < RageArch::UseCase::Base
|
|
67
|
+
use_case_symbol :posts_create
|
|
68
|
+
ar_dep :post_store, Post # auto-creates an AR adapter if :post_store is not registered
|
|
69
|
+
|
|
70
|
+
def call(params = {})
|
|
71
|
+
post = post_store.build(params)
|
|
72
|
+
return failure(post.errors.full_messages) unless post_store.save(post)
|
|
73
|
+
success(post: post)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
If `:post_store` is registered in the container, that implementation is used. Otherwise, `RageArch::Deps::ActiveRecord.for(Post)` is used as fallback.
|
|
79
|
+
|
|
61
80
|
---
|
|
62
81
|
|
|
63
82
|
### `RageArch::Container` — dependency registration
|
|
64
83
|
|
|
65
84
|
```ruby
|
|
85
|
+
# Register by instance
|
|
66
86
|
RageArch.register(:order_store, MyApp::Deps::OrderStore.new)
|
|
67
|
-
|
|
68
|
-
|
|
87
|
+
|
|
88
|
+
# Register with a block (lazy evaluation)
|
|
89
|
+
RageArch.register(:mailer) { Mailer.new }
|
|
90
|
+
|
|
91
|
+
# Register an ActiveRecord model as dep (wraps it automatically)
|
|
92
|
+
RageArch.register_ar(:user_store, User)
|
|
93
|
+
|
|
94
|
+
# Resolve
|
|
95
|
+
RageArch.resolve(:order_store) # => the registered implementation
|
|
96
|
+
|
|
97
|
+
# Check if registered
|
|
98
|
+
RageArch.registered?(:order_store) # => true
|
|
69
99
|
```
|
|
70
100
|
|
|
71
101
|
---
|
|
72
102
|
|
|
103
|
+
### Dependencies (Deps)
|
|
104
|
+
|
|
105
|
+
A dep is any object that a use case needs from the outside world: persistence, mailers, external APIs, caches, etc. No base class required — any Ruby object can be a dep.
|
|
106
|
+
|
|
107
|
+
#### Writing a dep manually
|
|
108
|
+
|
|
109
|
+
```ruby
|
|
110
|
+
# app/deps/posts/post_store.rb
|
|
111
|
+
module Posts
|
|
112
|
+
class PostStore
|
|
113
|
+
def build(attrs = {})
|
|
114
|
+
Post.new(attrs)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def save(record)
|
|
118
|
+
record.save
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def find(id)
|
|
122
|
+
Post.find_by(id: id)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def list(filters: {})
|
|
126
|
+
Post.where(filters).to_a
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Register it in `config/initializers/rage_arch.rb`:
|
|
133
|
+
|
|
134
|
+
```ruby
|
|
135
|
+
RageArch.register(:post_store, Posts::PostStore.new)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### ActiveRecord dep (generated)
|
|
139
|
+
|
|
140
|
+
For deps that simply wrap an AR model with standard CRUD, use the generator:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
rails g rage_arch:ar_dep post_store Post
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
This creates `app/deps/posts/post_store.rb` with `build`, `find`, `save`, `update`, `destroy`, and `list` methods backed by `RageArch::Deps::ActiveRecord.for(Post)`.
|
|
147
|
+
|
|
148
|
+
#### Generating a dep from use case analysis
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
rails g rage_arch:dep post_store
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Scans your use cases for method calls on `:post_store` and generates a class with stub methods for each one. If the file already exists, only missing methods are added.
|
|
155
|
+
|
|
156
|
+
#### Switching dep implementations
|
|
157
|
+
|
|
158
|
+
Use `dep_switch` to swap between multiple implementations of the same dep:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# Interactive — lists all available implementations and prompts you to choose
|
|
162
|
+
rails g rage_arch:dep_switch post_store
|
|
163
|
+
|
|
164
|
+
# Direct — activate a specific implementation
|
|
165
|
+
rails g rage_arch:dep_switch post_store PostgresPostStore
|
|
166
|
+
|
|
167
|
+
# Switch to ActiveRecord adapter
|
|
168
|
+
rails g rage_arch:dep_switch post_store ar
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
The generator scans `app/deps/` for files matching the symbol, updates `config/initializers/rage_arch.rb` by commenting out the old registration and adding the new one.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
73
175
|
### `RageArch::Controller` — thin controller mixin
|
|
74
176
|
|
|
75
177
|
```ruby
|
|
@@ -84,6 +186,18 @@ end
|
|
|
84
186
|
- `run_result(symbol, params)` — runs and returns the `Result` directly
|
|
85
187
|
- `flash_errors(result)` — sets `flash.now[:alert]` from `result.errors`
|
|
86
188
|
|
|
189
|
+
**API controller example (JSON):**
|
|
190
|
+
|
|
191
|
+
```ruby
|
|
192
|
+
class Api::PostsController < ApplicationController
|
|
193
|
+
def create
|
|
194
|
+
run :posts_create, post_params,
|
|
195
|
+
success: ->(r) { render json: r.value[:post], status: :created },
|
|
196
|
+
failure: ->(r) { render json: { errors: r.errors }, status: :unprocessable_entity }
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
```
|
|
200
|
+
|
|
87
201
|
---
|
|
88
202
|
|
|
89
203
|
### `RageArch::EventPublisher` — domain events
|
|
@@ -147,8 +261,11 @@ end
|
|
|
147
261
|
| `rails g rage_arch:scaffold Post title:string --api` | Same but API-only (JSON responses) |
|
|
148
262
|
| `rails g rage_arch:scaffold Post title:string --skip-model` | Skip model/migration if it already exists |
|
|
149
263
|
| `rails g rage_arch:use_case CreateOrder` | Generates a base use case file |
|
|
264
|
+
| `rails g rage_arch:use_case orders/create` | Generates a namespaced use case (`Orders::Create`) |
|
|
150
265
|
| `rails g rage_arch:dep post_store` | Generates a dep class by scanning method calls in use cases |
|
|
151
266
|
| `rails g rage_arch:ar_dep post_store Post` | Generates a dep that wraps an ActiveRecord model |
|
|
267
|
+
| `rails g rage_arch:dep_switch post_store` | Lists implementations and switches which one is registered |
|
|
268
|
+
| `rails g rage_arch:dep_switch post_store PostgresPostStore` | Directly activates a specific implementation |
|
|
152
269
|
|
|
153
270
|
---
|
|
154
271
|
|
|
@@ -179,15 +296,51 @@ publisher.clear
|
|
|
179
296
|
|
|
180
297
|
---
|
|
181
298
|
|
|
299
|
+
## Configuration
|
|
300
|
+
|
|
301
|
+
```ruby
|
|
302
|
+
# config/application.rb or config/initializers/rage_arch.rb
|
|
303
|
+
|
|
304
|
+
# Disable automatic event publishing when use cases finish (default: true)
|
|
305
|
+
config.rage_arch.auto_publish_events = false
|
|
306
|
+
|
|
307
|
+
# Disable boot verification (default: true)
|
|
308
|
+
config.rage_arch.verify_deps = false
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
182
313
|
## Boot verification
|
|
183
314
|
|
|
184
|
-
At boot, `RageArch.verify_deps!` runs automatically and raises if
|
|
315
|
+
At boot, `RageArch.verify_deps!` runs automatically and raises if it finds wiring problems. It checks:
|
|
316
|
+
|
|
317
|
+
- Every dep declared with `deps :symbol` is registered in the container
|
|
318
|
+
- Every method called on a dep is implemented by the registered object (via static analysis)
|
|
319
|
+
- Every use case declared with `use_cases :symbol` exists in the registry
|
|
320
|
+
|
|
321
|
+
Example error output:
|
|
322
|
+
|
|
323
|
+
```
|
|
324
|
+
RageArch boot verification failed:
|
|
325
|
+
UseCase :posts_create (Posts::Create) declares dep :post_store — not registered in container
|
|
326
|
+
UseCase :posts_create (Posts::Create) calls :post_store#save — Posts::PostStore does not implement #save
|
|
327
|
+
UseCase :posts_notify (Posts::Notify) declares use_cases :email_send — not registered in use case registry
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Disable with `config.rage_arch.verify_deps = false`.
|
|
185
331
|
|
|
186
332
|
---
|
|
187
333
|
|
|
188
334
|
## Instrumentation
|
|
189
335
|
|
|
190
|
-
Every use case emits `"
|
|
336
|
+
Every use case emits `"rage_arch.use_case.run"` via `ActiveSupport::Notifications` with payload `symbol`, `params`, `success`, `errors`, `result`.
|
|
337
|
+
|
|
338
|
+
```ruby
|
|
339
|
+
ActiveSupport::Notifications.subscribe("rage_arch.use_case.run") do |*args|
|
|
340
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
|
341
|
+
Rails.logger.info "[UseCase] #{event.payload[:symbol]} (#{event.duration.round}ms) success=#{event.payload[:success]}"
|
|
342
|
+
end
|
|
343
|
+
```
|
|
191
344
|
|
|
192
345
|
---
|
|
193
346
|
|
|
@@ -15,7 +15,7 @@ module RageArch
|
|
|
15
15
|
def create_ar_dep
|
|
16
16
|
@extra_methods = extra_methods
|
|
17
17
|
template "ar_dep.rb.tt", File.join("app/deps", module_dir, "#{dep_file_name}.rb")
|
|
18
|
-
say "Register in config/initializers/rage_arch.rb:
|
|
18
|
+
say "Register in config/initializers/rage_arch.rb: RageArch.register(:#{symbol_name}, #{full_class_name}.new)", :green
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
STANDARD_AR_METHODS = %i[build find save update destroy list].freeze
|
|
@@ -18,7 +18,7 @@ module RageArch
|
|
|
18
18
|
if options.empty?
|
|
19
19
|
say "No implementations found for :#{symbol}.", :red
|
|
20
20
|
say "Create a dep with: rails g rage_arch:dep #{symbol} [ClassName]"
|
|
21
|
-
say "Or add
|
|
21
|
+
say "Or add RageArch.register_ar(:#{symbol}, Model) in config/initializers/rage_arch.rb", :red
|
|
22
22
|
return
|
|
23
23
|
end
|
|
24
24
|
chosen = if class_name_arg.present?
|
|
@@ -48,19 +48,19 @@ module RageArch
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def initializer_path
|
|
51
|
-
File.join(destination_root, "config", "initializers", "
|
|
51
|
+
File.join(destination_root, "config", "initializers", "rage_arch.rb")
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def find_ar_registration(symbol)
|
|
55
55
|
path = initializer_path
|
|
56
56
|
return nil unless File.exist?(path)
|
|
57
57
|
content = File.read(path)
|
|
58
|
-
# Match active or commented:
|
|
58
|
+
# Match active or commented: RageArch.register_ar(:post_store, Post) or RageArch.register_ar :post_store, Post
|
|
59
59
|
content.each_line do |line|
|
|
60
60
|
stripped = line.strip
|
|
61
61
|
next if stripped.start_with?("#")
|
|
62
|
-
if stripped =~ /
|
|
63
|
-
stripped =~ /
|
|
62
|
+
if stripped =~ /RageArch\.register_ar\s*\(\s*:\s*#{Regexp.escape(symbol)}\s*,\s*(\w+)\s*\)/ ||
|
|
63
|
+
stripped =~ /RageArch\.register_ar\s+:\s*#{Regexp.escape(symbol)}\s*,\s*(\w+)/
|
|
64
64
|
return $1
|
|
65
65
|
end
|
|
66
66
|
end
|
|
@@ -68,8 +68,8 @@ module RageArch
|
|
|
68
68
|
content.each_line do |line|
|
|
69
69
|
stripped = line.strip.delete_prefix("#").strip
|
|
70
70
|
next if stripped.empty?
|
|
71
|
-
if stripped =~ /
|
|
72
|
-
stripped =~ /
|
|
71
|
+
if stripped =~ /RageArch\.register_ar\s*\(\s*:\s*#{Regexp.escape(symbol)}\s*,\s*(\w+)\s*\)/ ||
|
|
72
|
+
stripped =~ /RageArch\.register_ar\s+:\s*#{Regexp.escape(symbol)}\s*,\s*(\w+)/
|
|
73
73
|
return $1
|
|
74
74
|
end
|
|
75
75
|
end
|
|
@@ -160,20 +160,20 @@ module RageArch
|
|
|
160
160
|
content = comment_line_matching(content, symbol, :register_ar)
|
|
161
161
|
# Uncomment or add the chosen registration
|
|
162
162
|
chosen_line = option[:type] == :ar ?
|
|
163
|
-
"
|
|
164
|
-
"
|
|
163
|
+
"RageArch.register_ar(:#{symbol}, #{option[:model]})" :
|
|
164
|
+
"RageArch.register(:#{symbol}, #{option[:name]}.new)"
|
|
165
165
|
content = uncomment_or_add(content, symbol, option, chosen_line)
|
|
166
166
|
File.write(path, content)
|
|
167
167
|
end
|
|
168
168
|
|
|
169
169
|
def comment_line_matching(content, symbol, form)
|
|
170
170
|
if form == :register
|
|
171
|
-
content.gsub(/^(\s*)(
|
|
171
|
+
content.gsub(/^(\s*)(RageArch\.register\(:#{Regexp.escape(symbol)},\s*\S+\.new\))\s*$/, '\1# \2')
|
|
172
172
|
else
|
|
173
173
|
# register_ar with parens or with space
|
|
174
174
|
content
|
|
175
|
-
.gsub(/^(\s*)(
|
|
176
|
-
.gsub(/^(\s*)(
|
|
175
|
+
.gsub(/^(\s*)(RageArch\.register_ar\s*\(\s*:\s*#{Regexp.escape(symbol)}\s*,\s*\S+\s*\))\s*$/, '\1# \2')
|
|
176
|
+
.gsub(/^(\s*)(RageArch\.register_ar\s+:\s*#{Regexp.escape(symbol)}\s*,\s*\S+)\s*$/, '\1# \2')
|
|
177
177
|
end
|
|
178
178
|
end
|
|
179
179
|
|
|
@@ -182,18 +182,18 @@ module RageArch
|
|
|
182
182
|
model = option[:model]
|
|
183
183
|
# Uncomment if there is a commented register_ar line for this symbol and model
|
|
184
184
|
content = content.gsub(
|
|
185
|
-
/^(\s*)#\s*(
|
|
185
|
+
/^(\s*)#\s*(RageArch\.register_ar\s*\(\s*:\s*#{Regexp.escape(symbol)}\s*,\s*#{Regexp.escape(model)}\s*\))\s*$/,
|
|
186
186
|
'\1\2'
|
|
187
187
|
)
|
|
188
188
|
content = content.gsub(
|
|
189
|
-
/^(\s*)#\s*(
|
|
189
|
+
/^(\s*)#\s*(RageArch\.register_ar\s+:\s*#{Regexp.escape(symbol)}\s*,\s*#{Regexp.escape(model)})\s*$/,
|
|
190
190
|
'\1\2'
|
|
191
191
|
)
|
|
192
192
|
else
|
|
193
193
|
class_name = option[:name]
|
|
194
|
-
# Uncomment if there is a commented
|
|
194
|
+
# Uncomment if there is a commented RageArch.register line for this symbol and class
|
|
195
195
|
content = content.gsub(
|
|
196
|
-
/^(\s*)#\s*(
|
|
196
|
+
/^(\s*)#\s*(RageArch\.register\(:#{Regexp.escape(symbol)},\s*#{Regexp.escape(class_name)}\.new\))\s*$/,
|
|
197
197
|
'\1\2'
|
|
198
198
|
)
|
|
199
199
|
end
|
|
@@ -12,7 +12,7 @@ module RageArch
|
|
|
12
12
|
class_option :skip_model, type: :boolean, default: false, desc: "Skip model and migration (use when model already exists)"
|
|
13
13
|
class_option :api, type: :boolean, default: false, desc: "Generate API-only controller (JSON responses, no views)"
|
|
14
14
|
|
|
15
|
-
desc "Generate a full
|
|
15
|
+
desc "Generate a full RageArch CRUD: model, migration, use cases (list/show/create/update/destroy), dep (AR), controller, and routes. With --api: JSON responses only, no views."
|
|
16
16
|
def create_all
|
|
17
17
|
create_model_and_migration
|
|
18
18
|
create_use_cases
|
|
@@ -70,7 +70,7 @@ module RageArch
|
|
|
70
70
|
return unless File.exist?(initializer_path)
|
|
71
71
|
content = File.read(initializer_path)
|
|
72
72
|
return if content.include?("register_ar(:#{repo_symbol})")
|
|
73
|
-
inject_line = "
|
|
73
|
+
inject_line = " RageArch.register_ar(:#{repo_symbol}, #{model_class_name})\n"
|
|
74
74
|
content.sub!(/(Rails\.application\.config\.after_initialize do\s*\n)/m, "\\1#{inject_line}")
|
|
75
75
|
File.write(initializer_path, content)
|
|
76
76
|
say_status :inject, "config/initializers/rage_arch.rb (register_ar :#{repo_symbol})", :green
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Dep for :<%= repo_symbol %>. Wraps the <%= model_class_name %> Active Record model.
|
|
4
|
-
# Registered by
|
|
4
|
+
# Registered by rage_arch:scaffold in config/initializers/rage_arch.rb
|
|
5
5
|
module <%= module_name %>
|
|
6
6
|
class <%= singular_name.camelize %>Repo
|
|
7
7
|
def initialize
|
data/lib/rage_arch/container.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module RageArch
|
|
4
4
|
# Container to register and resolve dependencies by symbol.
|
|
5
|
-
# Usage:
|
|
5
|
+
# Usage: RageArch.register(:order_store, MyAdapter.new); RageArch.resolve(:order_store)
|
|
6
6
|
class Container
|
|
7
7
|
class << self
|
|
8
8
|
def register(symbol, implementation = nil, &block)
|
|
@@ -4,7 +4,7 @@ require "set"
|
|
|
4
4
|
|
|
5
5
|
module RageArch
|
|
6
6
|
# Scans use case files to find dep symbols and the methods called on each dep.
|
|
7
|
-
# Used by the
|
|
7
|
+
# Used by the rage_arch:dep generator to create stub classes with the right methods.
|
|
8
8
|
# Also tracks which use case path each symbol appears in (for folder inference).
|
|
9
9
|
class DepScanner
|
|
10
10
|
def initialize(use_cases_root = nil)
|
|
@@ -4,7 +4,7 @@ module RageArch
|
|
|
4
4
|
module Deps
|
|
5
5
|
# Helper to use an Active Record model as a dep (minimal adapter).
|
|
6
6
|
# Usage: RageArch::Deps::ActiveRecord.for(Order) → object exposing build, find, etc. on Order.
|
|
7
|
-
# In the container:
|
|
7
|
+
# In the container: RageArch.register(:order_store, RageArch::Deps::ActiveRecord.for(Order))
|
|
8
8
|
class ActiveRecord
|
|
9
9
|
def self.for(model_class)
|
|
10
10
|
new(model_class)
|
|
@@ -8,7 +8,7 @@ module RageArch
|
|
|
8
8
|
# Setup in config/initializers/rage_arch.rb:
|
|
9
9
|
# publisher = RageArch::EventPublisher.new
|
|
10
10
|
# RageArch::UseCase::Base.wire_subscriptions_to(publisher)
|
|
11
|
-
#
|
|
11
|
+
# RageArch.register(:event_publisher, publisher)
|
|
12
12
|
class EventPublisher
|
|
13
13
|
def initialize
|
|
14
14
|
@handlers = Hash.new { |h, k| h[k] = [] }
|
|
@@ -5,7 +5,7 @@ module RageArch
|
|
|
5
5
|
# Use it to assert that a use case (or code) published expected events.
|
|
6
6
|
#
|
|
7
7
|
# publisher = RageArch::FakeEventPublisher.new
|
|
8
|
-
#
|
|
8
|
+
# RageArch.register(:event_publisher, publisher)
|
|
9
9
|
# RageArch::UseCase::Base.build(:create_post).call(title: "Hi")
|
|
10
10
|
# expect(publisher.published).to include(
|
|
11
11
|
# hash_including(event: :post_created, post_id: kind_of(Integer))
|
data/lib/rage_arch/railtie.rb
CHANGED
|
@@ -5,9 +5,9 @@ require_relative "controller"
|
|
|
5
5
|
|
|
6
6
|
module RageArch
|
|
7
7
|
class Railtie < ::Rails::Railtie
|
|
8
|
-
config.
|
|
9
|
-
config.
|
|
10
|
-
config.
|
|
8
|
+
config.rage_arch = ActiveSupport::OrderedOptions.new
|
|
9
|
+
config.rage_arch.auto_publish_events = true
|
|
10
|
+
config.rage_arch.verify_deps = true
|
|
11
11
|
|
|
12
12
|
# Load use case files so they register their symbols in the registry.
|
|
13
13
|
# Without this, build(:symbol) would fail until the use case constant was referenced.
|
|
@@ -25,7 +25,7 @@ module RageArch
|
|
|
25
25
|
# registered there would not be visible yet. Apps should call
|
|
26
26
|
# RageArch.verify_deps! manually at the end of their own after_initialize
|
|
27
27
|
# (config/initializers/rage_arch.rb), after all deps are registered.
|
|
28
|
-
# Set config.
|
|
28
|
+
# Set config.rage_arch.verify_deps = false to opt out.
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module RageArch
|
|
4
|
-
# RSpec matchers and helpers for testing
|
|
4
|
+
# RSpec matchers and helpers for testing RageArch use cases and results.
|
|
5
5
|
# In spec_helper.rb or rails_helper.rb add:
|
|
6
6
|
# require "rage_arch/rspec_matchers"
|
|
7
7
|
# Then use: expect(result).to succeed_with(post: post) or expect(result).to fail_with_errors(["error"])
|
data/lib/rage_arch/use_case.rb
CHANGED
|
@@ -33,7 +33,7 @@ module RageArch
|
|
|
33
33
|
def call(params = {})
|
|
34
34
|
sym = self.class.use_case_symbol
|
|
35
35
|
if defined?(ActiveSupport::Notifications)
|
|
36
|
-
ActiveSupport::Notifications.instrument("
|
|
36
|
+
ActiveSupport::Notifications.instrument("rage_arch.use_case.run", symbol: sym, params: params) do |payload|
|
|
37
37
|
result = super(params)
|
|
38
38
|
payload[:success] = result.success?
|
|
39
39
|
payload[:errors] = result.errors unless result.success?
|
|
@@ -66,8 +66,8 @@ module RageArch
|
|
|
66
66
|
|
|
67
67
|
def auto_publish_enabled?
|
|
68
68
|
return false if self.class.skip_auto_publish?
|
|
69
|
-
return true unless defined?(Rails) && Rails.application.config.respond_to?(:
|
|
70
|
-
Rails.application.config.
|
|
69
|
+
return true unless defined?(Rails) && Rails.application.config.respond_to?(:rage_arch) && Rails.application.config.rage_arch
|
|
70
|
+
Rails.application.config.rage_arch.auto_publish_events != false
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
73
|
|
data/lib/rage_arch/version.rb
CHANGED
data/lib/rage_arch.rb
CHANGED
|
@@ -16,7 +16,7 @@ module RageArch
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
# Registers a dep that uses Active Record for the given model.
|
|
19
|
-
# Example:
|
|
19
|
+
# Example: RageArch.register_ar(:user_store, User)
|
|
20
20
|
def register_ar(symbol, model_class)
|
|
21
21
|
register(symbol, Deps::ActiveRecord.for(model_class))
|
|
22
22
|
end
|
|
@@ -31,7 +31,7 @@ module RageArch
|
|
|
31
31
|
|
|
32
32
|
# Verifies that all deps and use_cases declared by registered use cases are
|
|
33
33
|
# available before the app handles any request. Call after all initializers run
|
|
34
|
-
# (done automatically by the Railtie unless config.
|
|
34
|
+
# (done automatically by the Railtie unless config.rage_arch.verify_deps = false).
|
|
35
35
|
#
|
|
36
36
|
# Raises RuntimeError listing every missing dep/use_case if any are absent.
|
|
37
37
|
# Returns true when everything is wired correctly.
|