axn 0.1.0.pre.alpha.2.8 → 0.1.0.pre.alpha.3
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/.cursor/rules/axn-framework-patterns.mdc +43 -0
- data/.cursor/rules/general-coding-standards.mdc +27 -0
- data/.cursor/rules/spec/testing-patterns.mdc +40 -0
- data/CHANGELOG.md +47 -0
- data/Rakefile +12 -2
- data/docs/.vitepress/config.mjs +8 -3
- data/docs/advanced/conventions.md +2 -2
- data/docs/advanced/mountable.md +562 -0
- data/docs/advanced/profiling.md +355 -0
- data/docs/advanced/rough.md +1 -1
- data/docs/index.md +5 -3
- data/docs/intro/about.md +1 -1
- data/docs/intro/overview.md +5 -5
- data/docs/recipes/memoization.md +2 -2
- data/docs/recipes/rubocop-integration.md +38 -284
- data/docs/recipes/testing.md +14 -14
- data/docs/recipes/validating-user-input.md +1 -1
- data/docs/reference/async.md +160 -0
- data/docs/reference/axn-result.md +107 -0
- data/docs/reference/class.md +123 -25
- data/docs/reference/configuration.md +191 -10
- data/docs/reference/instance.md +14 -29
- data/docs/strategies/index.md +21 -21
- data/docs/strategies/transaction.md +1 -1
- data/docs/usage/setup.md +14 -0
- data/docs/usage/steps.md +7 -7
- data/docs/usage/using.md +23 -12
- data/docs/usage/writing.md +92 -11
- data/lib/axn/async/adapters/active_job.rb +65 -0
- data/lib/axn/async/adapters/disabled.rb +26 -0
- data/lib/axn/async/adapters/sidekiq.rb +74 -0
- data/lib/axn/async/adapters.rb +26 -0
- data/lib/axn/async.rb +61 -0
- data/lib/{action → axn}/configuration.rb +21 -3
- data/lib/{action → axn}/context.rb +21 -4
- data/lib/{action → axn}/core/automatic_logging.rb +6 -6
- data/lib/axn/core/context/facade.rb +69 -0
- data/lib/{action → axn}/core/context/facade_inspector.rb +31 -4
- data/lib/{action → axn}/core/context/internal.rb +5 -5
- data/lib/{action → axn}/core/contract.rb +43 -46
- data/lib/{action → axn}/core/contract_for_subfields.rb +30 -35
- data/lib/{action → axn}/core/contract_validation.rb +16 -6
- data/lib/axn/core/contract_validation_for_subfields.rb +158 -0
- data/lib/axn/core/field_resolvers/extract.rb +32 -0
- data/lib/axn/core/field_resolvers/model.rb +63 -0
- data/lib/axn/core/field_resolvers.rb +24 -0
- data/lib/{action → axn}/core/flow/callbacks.rb +7 -7
- data/lib/{action → axn}/core/flow/exception_execution.rb +4 -13
- data/lib/{action → axn}/core/flow/handlers/base_descriptor.rb +3 -2
- data/lib/{action → axn}/core/flow/handlers/descriptors/callback_descriptor.rb +2 -2
- data/lib/{action → axn}/core/flow/handlers/descriptors/message_descriptor.rb +6 -6
- data/lib/{action → axn}/core/flow/handlers/invoker.rb +6 -6
- data/lib/{action → axn}/core/flow/handlers/matcher.rb +5 -5
- data/lib/{action → axn}/core/flow/handlers/registry.rb +3 -1
- data/lib/{action → axn}/core/flow/handlers/resolvers/base_resolver.rb +1 -1
- data/lib/{action → axn}/core/flow/handlers/resolvers/callback_resolver.rb +2 -2
- data/lib/{action → axn}/core/flow/handlers/resolvers/message_resolver.rb +12 -3
- data/lib/axn/core/flow/handlers.rb +20 -0
- data/lib/{action → axn}/core/flow/messages.rb +7 -7
- data/lib/{action → axn}/core/flow.rb +4 -4
- data/lib/{action → axn}/core/hooks.rb +16 -5
- data/lib/{action → axn}/core/logging.rb +3 -3
- data/lib/{action → axn}/core/nesting_tracking.rb +1 -1
- data/lib/axn/core/profiling.rb +124 -0
- data/lib/{action → axn}/core/timing.rb +1 -1
- data/lib/axn/core/tracing.rb +17 -0
- data/lib/axn/core/use_strategy.rb +29 -0
- data/lib/{action → axn}/core/validation/fields.rb +26 -2
- data/lib/{action → axn}/core/validation/subfields.rb +14 -12
- data/lib/axn/core/validation/validators/model_validator.rb +36 -0
- data/lib/axn/core/validation/validators/type_validator.rb +80 -0
- data/lib/{action → axn}/core/validation/validators/validate_validator.rb +12 -2
- data/lib/axn/core.rb +123 -0
- data/lib/{action → axn}/exceptions.rb +12 -2
- data/lib/axn/factory.rb +102 -34
- data/lib/axn/internal/logging.rb +26 -0
- data/lib/axn/internal/registry.rb +87 -0
- data/lib/axn/mountable/descriptor.rb +76 -0
- data/lib/axn/mountable/helpers/class_builder.rb +162 -0
- data/lib/axn/mountable/helpers/mounter.rb +33 -0
- data/lib/axn/mountable/helpers/namespace_manager.rb +66 -0
- data/lib/axn/mountable/helpers/validator.rb +112 -0
- data/lib/axn/mountable/inherit_profiles.rb +72 -0
- data/lib/axn/mountable/mounting_strategies/_base.rb +83 -0
- data/lib/axn/mountable/mounting_strategies/axn.rb +48 -0
- data/lib/axn/mountable/mounting_strategies/enqueue_all.rb +55 -0
- data/lib/axn/mountable/mounting_strategies/method.rb +95 -0
- data/lib/axn/mountable/mounting_strategies/step.rb +69 -0
- data/lib/axn/mountable/mounting_strategies.rb +32 -0
- data/lib/axn/mountable.rb +85 -0
- data/lib/axn/rails/engine.rb +51 -0
- data/lib/axn/rails/generators/axn_generator.rb +68 -0
- data/lib/axn/rails/generators/templates/action.rb.erb +17 -0
- data/lib/axn/rails/generators/templates/action_spec.rb.erb +25 -0
- data/lib/{action → axn}/result.rb +30 -11
- data/lib/{action → axn}/strategies/transaction.rb +1 -1
- data/lib/axn/strategies.rb +20 -0
- data/lib/axn/testing/spec_helpers.rb +6 -8
- data/lib/axn/util/memoization.rb +20 -0
- data/lib/axn/version.rb +1 -1
- data/lib/axn.rb +17 -16
- data/lib/rubocop/cop/axn/README.md +23 -23
- data/lib/rubocop/cop/axn/unchecked_result.rb +138 -17
- metadata +88 -64
- data/.rspec +0 -3
- data/.rubocop.yml +0 -76
- data/.tool-versions +0 -1
- data/docs/reference/action-result.md +0 -37
- data/lib/action/attachable/base.rb +0 -43
- data/lib/action/attachable/steps.rb +0 -63
- data/lib/action/attachable/subactions.rb +0 -70
- data/lib/action/attachable.rb +0 -17
- data/lib/action/core/context/facade.rb +0 -48
- data/lib/action/core/flow/handlers.rb +0 -20
- data/lib/action/core/tracing.rb +0 -17
- data/lib/action/core/use_strategy.rb +0 -30
- data/lib/action/core/validation/validators/model_validator.rb +0 -34
- data/lib/action/core/validation/validators/type_validator.rb +0 -30
- data/lib/action/core.rb +0 -108
- data/lib/action/enqueueable/via_sidekiq.rb +0 -76
- data/lib/action/enqueueable.rb +0 -13
- data/lib/action/strategies.rb +0 -48
- data/lib/axn/util.rb +0 -24
- data/package.json +0 -10
- data/yarn.lock +0 -1166
@@ -0,0 +1,355 @@
|
|
1
|
+
# Profiling
|
2
|
+
|
3
|
+
Axn supports performance profiling using [Vernier](https://github.com/Shopify/vernier), a Ruby sampling profiler that provides detailed insights into your action's performance characteristics.
|
4
|
+
|
5
|
+
## Overview
|
6
|
+
|
7
|
+
Profiling helps you identify performance bottlenecks in your actions by capturing detailed execution traces. Vernier is particularly useful for:
|
8
|
+
|
9
|
+
- Identifying slow methods and code paths
|
10
|
+
- Understanding memory allocation patterns
|
11
|
+
- Analyzing call stacks and execution flow
|
12
|
+
- Optimizing performance-critical actions
|
13
|
+
|
14
|
+
## Setup
|
15
|
+
|
16
|
+
### 1. Install Vernier
|
17
|
+
|
18
|
+
Add the Vernier gem to your Gemfile:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
# Gemfile
|
22
|
+
gem 'vernier', '~> 0.1'
|
23
|
+
```
|
24
|
+
|
25
|
+
Then run:
|
26
|
+
|
27
|
+
```bash
|
28
|
+
bundle install
|
29
|
+
```
|
30
|
+
|
31
|
+
**Note:** Vernier is not included as a dependency of Axn, so you must explicitly add it to your Gemfile if you want to use profiling features.
|
32
|
+
|
33
|
+
### 2. Enable Profiling
|
34
|
+
|
35
|
+
No global configuration is needed! Simply call `profile` on the actions you want to profile.
|
36
|
+
|
37
|
+
## Basic Usage
|
38
|
+
|
39
|
+
Profiling is enabled per-action by calling the `profile` method. You can only call `profile` **once per action** - subsequent calls will override the previous one. This prevents accidental profiling of all actions and ensures you only profile what you intend to analyze.
|
40
|
+
|
41
|
+
### Simple Profiling
|
42
|
+
|
43
|
+
Enable profiling on any action:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
class UserCreation
|
47
|
+
include Axn
|
48
|
+
|
49
|
+
# Always profile this action
|
50
|
+
profile
|
51
|
+
|
52
|
+
expects :user_params
|
53
|
+
|
54
|
+
def call
|
55
|
+
user = User.create!(user_params)
|
56
|
+
send_welcome_email(user)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def send_welcome_email(user)
|
62
|
+
UserMailer.welcome(user).deliver_now
|
63
|
+
end
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
67
|
+
### Conditional Profiling
|
68
|
+
|
69
|
+
Profile only under specific conditions:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
class DataProcessing
|
73
|
+
include Axn
|
74
|
+
|
75
|
+
# Profile only when processing large datasets (only one profile call per action)
|
76
|
+
profile if: -> { record_count > 1000 }
|
77
|
+
|
78
|
+
expects :records, :record_count
|
79
|
+
|
80
|
+
def call
|
81
|
+
records.each { |record| process_record(record) }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
```
|
85
|
+
|
86
|
+
**Alternative using a method:**
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
class DataProcessing
|
90
|
+
include Axn
|
91
|
+
|
92
|
+
# Profile using a method (only one profile call per action)
|
93
|
+
profile if: :should_profile?
|
94
|
+
|
95
|
+
expects :records, :record_count, :debug_mode, type: :boolean, default: false
|
96
|
+
|
97
|
+
def should_profile?
|
98
|
+
record_count > 1000 || debug_mode
|
99
|
+
end
|
100
|
+
|
101
|
+
def call
|
102
|
+
records.each { |record| process_record(record) }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
```
|
106
|
+
|
107
|
+
|
108
|
+
## Advanced Usage
|
109
|
+
|
110
|
+
### Sampling Rate Control
|
111
|
+
|
112
|
+
Adjust the sampling rate per action:
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
class DevelopmentAction
|
116
|
+
include Axn
|
117
|
+
|
118
|
+
# High sampling rate for development (more detailed data)
|
119
|
+
profile(sample_rate: 0.5) if Rails.env.development?
|
120
|
+
|
121
|
+
def call
|
122
|
+
# Action logic
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
class ProductionAction
|
127
|
+
include Axn
|
128
|
+
|
129
|
+
# Low sampling rate for production (minimal overhead)
|
130
|
+
profile(sample_rate: 0.01) if Rails.env.production?
|
131
|
+
|
132
|
+
def call
|
133
|
+
# Action logic
|
134
|
+
end
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
138
|
+
### Custom Output Directory
|
139
|
+
|
140
|
+
Organize profiles by environment or feature:
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
class MyAction
|
144
|
+
include Axn
|
145
|
+
|
146
|
+
# Custom output directory
|
147
|
+
profile(output_dir: Rails.root.join("tmp", "profiles", Rails.env))
|
148
|
+
|
149
|
+
def call
|
150
|
+
# Action logic
|
151
|
+
end
|
152
|
+
end
|
153
|
+
```
|
154
|
+
|
155
|
+
### Multiple Conditions
|
156
|
+
|
157
|
+
Combine multiple profiling conditions:
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
class ComplexAction
|
161
|
+
include Axn
|
162
|
+
|
163
|
+
# Profile when debug mode is enabled OR when processing admin users
|
164
|
+
profile if: -> { debug_mode || user.admin? }
|
165
|
+
|
166
|
+
expects :user, :debug_mode, type: :boolean, default: false
|
167
|
+
|
168
|
+
def call
|
169
|
+
# Complex logic
|
170
|
+
end
|
171
|
+
end
|
172
|
+
```
|
173
|
+
|
174
|
+
## Viewing and Analyzing Profiles
|
175
|
+
|
176
|
+
### 1. Generate Profile Data
|
177
|
+
|
178
|
+
Run your action with profiling enabled:
|
179
|
+
|
180
|
+
```ruby
|
181
|
+
# This will generate a profile file if conditions are met
|
182
|
+
result = UserCreation.call(user_params: { name: "John", email: "john@example.com" })
|
183
|
+
```
|
184
|
+
|
185
|
+
### 2. Locate Profile Files
|
186
|
+
|
187
|
+
Profile files are saved as JSON in your configured output directory:
|
188
|
+
|
189
|
+
```bash
|
190
|
+
# Default location
|
191
|
+
ls tmp/profiles/
|
192
|
+
|
193
|
+
# Example output
|
194
|
+
axn_UserCreation_1703123456.json
|
195
|
+
axn_DataProcessing_1703123457.json
|
196
|
+
```
|
197
|
+
|
198
|
+
### 3. View in Firefox Profiler
|
199
|
+
|
200
|
+
1. Open [profiler.firefox.com](https://profiler.firefox.com/)
|
201
|
+
2. Click "Load a profile from file"
|
202
|
+
3. Select your generated JSON file
|
203
|
+
4. Analyze the performance data
|
204
|
+
|
205
|
+
### 4. Understanding the Profile
|
206
|
+
|
207
|
+
The Firefox Profiler provides several views:
|
208
|
+
|
209
|
+
- **Call Tree**: Shows the complete call stack with timing
|
210
|
+
- **Flame Graph**: Visual representation of call stacks
|
211
|
+
- **Stack Chart**: Timeline view of function calls
|
212
|
+
- **Markers**: Custom markers and events
|
213
|
+
|
214
|
+
## Best Practices
|
215
|
+
|
216
|
+
### 1. Use Conditional Profiling
|
217
|
+
|
218
|
+
Avoid profiling all actions in production:
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
# Good: Conditional profiling
|
222
|
+
profile if: -> { Rails.env.development? || debug_mode }
|
223
|
+
|
224
|
+
# Avoid: Always profiling in production
|
225
|
+
profile # This can impact performance
|
226
|
+
```
|
227
|
+
|
228
|
+
### 2. Appropriate Sampling Rates
|
229
|
+
|
230
|
+
Choose sampling rates based on your environment:
|
231
|
+
|
232
|
+
```ruby
|
233
|
+
class MyAction
|
234
|
+
include Axn
|
235
|
+
|
236
|
+
# High detail for debugging
|
237
|
+
profile(sample_rate: 0.5) if Rails.env.development?
|
238
|
+
|
239
|
+
# Moderate sampling for staging
|
240
|
+
profile(sample_rate: 0.1) if Rails.env.staging?
|
241
|
+
|
242
|
+
# Minimal overhead for production
|
243
|
+
profile(sample_rate: 0.01) if Rails.env.production?
|
244
|
+
|
245
|
+
def call
|
246
|
+
# Action logic
|
247
|
+
end
|
248
|
+
end
|
249
|
+
```
|
250
|
+
|
251
|
+
### 3. Profile Specific Scenarios
|
252
|
+
|
253
|
+
Focus on performance-critical paths:
|
254
|
+
|
255
|
+
```ruby
|
256
|
+
class OrderProcessing
|
257
|
+
include Axn
|
258
|
+
|
259
|
+
# Profile only expensive operations
|
260
|
+
profile if: -> { order.total > 1000 }
|
261
|
+
|
262
|
+
expects :order
|
263
|
+
|
264
|
+
def call
|
265
|
+
process_payment
|
266
|
+
send_confirmation
|
267
|
+
update_inventory
|
268
|
+
end
|
269
|
+
end
|
270
|
+
```
|
271
|
+
|
272
|
+
### 4. Clean Up Old Profiles
|
273
|
+
|
274
|
+
Implement profile cleanup to avoid disk space issues:
|
275
|
+
|
276
|
+
```ruby
|
277
|
+
# Add to a rake task or cron job
|
278
|
+
namespace :profiles do
|
279
|
+
desc "Clean up old profile files"
|
280
|
+
task cleanup: :environment do
|
281
|
+
profile_dir = Rails.root.join("tmp", "profiles")
|
282
|
+
Dir.glob(File.join(profile_dir, "*.json")).each do |file|
|
283
|
+
File.delete(file) if File.mtime(file) < 7.days.ago
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
```
|
288
|
+
|
289
|
+
## Troubleshooting
|
290
|
+
|
291
|
+
### Vernier Not Available
|
292
|
+
|
293
|
+
If you see this error:
|
294
|
+
|
295
|
+
```
|
296
|
+
LoadError: Vernier gem is not loaded. Add `gem 'vernier', '~> 0.1'` to your Gemfile to enable profiling.
|
297
|
+
```
|
298
|
+
|
299
|
+
Make sure to:
|
300
|
+
1. Add `vernier` to your Gemfile
|
301
|
+
2. Run `bundle install`
|
302
|
+
3. Restart your application
|
303
|
+
|
304
|
+
### No Profile Files Generated
|
305
|
+
|
306
|
+
If profile files aren't being generated:
|
307
|
+
|
308
|
+
1. Verify your action has `profile` enabled
|
309
|
+
2. Ensure profiling conditions are met
|
310
|
+
3. Check the output directory exists and is writable
|
311
|
+
|
312
|
+
### Performance Impact
|
313
|
+
|
314
|
+
Profiling adds overhead to your application:
|
315
|
+
|
316
|
+
- **Sampling overhead**: ~1-5% depending on sample rate
|
317
|
+
- **File I/O**: Profile files are written to disk
|
318
|
+
- **Memory usage**: Slight increase due to sampling
|
319
|
+
|
320
|
+
Use appropriate sampling rates and conditional profiling to minimize impact.
|
321
|
+
|
322
|
+
## Integration with Other Tools
|
323
|
+
|
324
|
+
### Datadog Integration
|
325
|
+
|
326
|
+
Combine profiling with Datadog tracing:
|
327
|
+
|
328
|
+
```ruby
|
329
|
+
Axn.configure do |c|
|
330
|
+
# Datadog tracing
|
331
|
+
c.wrap_with_trace = proc do |resource, &action|
|
332
|
+
Datadog::Tracing.trace("Action", resource:) do
|
333
|
+
action.call
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
class MyAction
|
339
|
+
include Axn
|
340
|
+
|
341
|
+
# Profiling with custom options
|
342
|
+
profile(sample_rate: 0.1)
|
343
|
+
|
344
|
+
def call
|
345
|
+
# Action logic
|
346
|
+
end
|
347
|
+
end
|
348
|
+
```
|
349
|
+
|
350
|
+
## Resources
|
351
|
+
|
352
|
+
- [Vernier GitHub Repository](https://github.com/Shopify/vernier)
|
353
|
+
- [Firefox Profiler](https://profiler.firefox.com/)
|
354
|
+
- [Ruby Performance Optimization Guide](https://ruby-doc.org/core-3.2.1/doc/performance_rdoc.html)
|
355
|
+
- [Axn Configuration Reference](/reference/configuration)
|
data/docs/advanced/rough.md
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
|
9
9
|
* `context_for_logging` (and decent #inspect support)
|
10
10
|
|
11
|
-
* Configuring logging (will default to Rails.logger if available, else fall back to basic Logger (but can explicitly set via e.g. `
|
11
|
+
* Configuring logging (will default to Rails.logger if available, else fall back to basic Logger (but can explicitly set via e.g. `Axn.config.logger = Logger.new($stdout`))
|
12
12
|
|
13
13
|
* Note `context_for_logging` is available (filtered to accessible attrs, filtering out sensitive values). Automatically passed into `on_exception` hook.
|
14
14
|
|
data/docs/index.md
CHANGED
@@ -22,11 +22,13 @@ hero:
|
|
22
22
|
|
23
23
|
features:
|
24
24
|
- title: Declarative interface
|
25
|
-
details:
|
25
|
+
details: Clear, explicit contracts for inputs and outputs with `expects` and `exposes`
|
26
26
|
- title: Exception swallowing
|
27
|
-
details:
|
27
|
+
details: Automatic error handling with user-safe error messages and internal logging
|
28
|
+
- title: Advanced Patterns
|
29
|
+
details: Mountable actions, workflow composition, and background processing capabilities
|
28
30
|
- title: Default Observability
|
29
|
-
details:
|
31
|
+
details: Built-in logging, timing, and error tracking out of the box
|
30
32
|
---
|
31
33
|
|
32
34
|
::: danger ALPHA RELEASE
|
data/docs/intro/about.md
CHANGED
@@ -17,7 +17,7 @@ A simple, declarative core API. Concise enough to pick up quickly, but sufficien
|
|
17
17
|
- Consistent return interface (including exception swallowing)
|
18
18
|
- Clear distinction between user-facing and internal errors
|
19
19
|
- Minimal boilerplate
|
20
|
-
- Easy
|
20
|
+
- Easy async execution (no need for a separate Worker class just to wrap a service call)
|
21
21
|
|
22
22
|
**Additional benefits devs get for free:**
|
23
23
|
|
data/docs/intro/overview.md
CHANGED
@@ -17,7 +17,7 @@ Your logic goes in a <abbr title="Plain Old Ruby Object">PORO</abbr>. The only r
|
|
17
17
|
|
18
18
|
```ruby
|
19
19
|
class Foo
|
20
|
-
include
|
20
|
+
include Axn
|
21
21
|
|
22
22
|
def call
|
23
23
|
log "Doesn't do much, but this technically works..."
|
@@ -31,7 +31,7 @@ Most actions require inputs, and many return values to the caller; no need for a
|
|
31
31
|
|
32
32
|
* `expects :foo` to declare inputs the class expects to receive.
|
33
33
|
|
34
|
-
You pass the `expect`ed keyword arguments to `call`, then reference their values as local `attr_reader`s.
|
34
|
+
You pass the `expect`ed keyword arguments to `call`, then reference their values as local `attr_reader`s. Use `optional: true` for fields that may be missing or blank.
|
35
35
|
|
36
36
|
* `exposes :bar` to declare any outputs the class will expose.
|
37
37
|
|
@@ -52,7 +52,7 @@ If any declared expectations or exposures are _not_ met the action will fail, se
|
|
52
52
|
|
53
53
|
```ruby
|
54
54
|
class Actions::Slack::Post
|
55
|
-
include
|
55
|
+
include Axn
|
56
56
|
VALID_CHANNELS = [ ... ]
|
57
57
|
|
58
58
|
expects :channel, default: VALID_CHANNELS.first, inclusion: { in: VALID_CHANNELS } # [!code focus:4]
|
@@ -76,7 +76,7 @@ end
|
|
76
76
|
## Return interface {#return-interface}
|
77
77
|
|
78
78
|
|
79
|
-
The return value of an
|
79
|
+
The return value of an Axn call is always an `Axn::Result`, which provides a consistent interface:
|
80
80
|
|
81
81
|
* `ok?` will return a boolean (false if any errors or exceptions occurred, otherwise true)
|
82
82
|
* if OK, `success` will return a string that is _safe to show end users_
|
@@ -140,7 +140,7 @@ When configuring custom error and success messages, remember to define your stat
|
|
140
140
|
|
141
141
|
```ruby
|
142
142
|
class MyAction
|
143
|
-
include
|
143
|
+
include Axn
|
144
144
|
|
145
145
|
# Static fallback messages first
|
146
146
|
success "Default success message"
|
data/docs/recipes/memoization.md
CHANGED
@@ -6,7 +6,7 @@ For instance, at Teamshares we automatically add memoization support (via [memo_
|
|
6
6
|
|
7
7
|
|
8
8
|
```ruby
|
9
|
-
|
9
|
+
Axn.configure do |c|
|
10
10
|
c.additional_includes = [TS::Memoization]
|
11
11
|
end
|
12
12
|
```
|
@@ -29,7 +29,7 @@ And with those pieces in place `memo` is available in all Actions:
|
|
29
29
|
|
30
30
|
```ruby
|
31
31
|
class ContrivedExample
|
32
|
-
include
|
32
|
+
include Axn
|
33
33
|
|
34
34
|
exposes :nums
|
35
35
|
|