README.md in metaractor-2.1.1 vs README.md in metaractor-3.0.0
- old
+ new
@@ -42,11 +42,11 @@
result = HighFiveUser.call # not passing user or user_id
result.failure?
# => true
result.valid?
# => false
-result.errors
+result.error_messages
# => ["Required parameters: (user_id or user)"]
```
See Interactor's [README](https://github.com/collectiveidea/interactor/blob/master/README.md) for more information.
@@ -66,24 +66,45 @@
Metaractor supports complex required parameter statements and you can chain these together in any manner using `and`, `or`, and `xor`.
```ruby
required and: [:token, or: [:recipient_id, :recipient] ]
```
+You can also mark a parameter as required with the `required` option:
+```ruby
+parameter :user, required: true
+```
+
### Optional Parameters
As optional parameters have no enforcement, they are merely advisory.
```ruby
optional :enable_logging
```
-### Skipping Blank Parameter Removal
+### Parameter Options
+Metaractor supports arbitrary parameter options. The following are currently built in.
+Note that you can specify a block of `required` or `optional` parameters and then use
+`parameter` or `parameters` to add options to one or more of them.
+
+#### Skipping Blank Parameter Removal
By default Metaractor removes blank values that are passed in. You may skip this behavior on a per-parameter basis:
```ruby
-allow_blank :name
+parameter :name, allow_blank: true
```
You may check to see if a parameter exists via `context.has_key?`.
+#### Default Values
+You can specify a default value for a parameter:
+```ruby
+optional :role, default: :user
+```
+
+This works with `allow_blank` and can also be anything that responds to `#call`.
+```ruby
+parameter :role, allow_blank: true, default: -> { context.default_role }
+```
+
### Custom Validation
Metaractor supports doing custom validation before any user supplied before_hooks run.
```ruby
validate_parameters do
if context.foo == :bar
@@ -159,10 +180,68 @@
# username: ['must be unique', 'must not be blank']
# }
# }
```
+### I18n
+As of v3.0.0, metaractor supports i18n along with structured errors.
+```ruby
+module Users
+ class UpdateUser
+ include Metaractor
+
+ optional :is_admin
+ optional :user
+
+ def call
+ fail_with_error!(
+ errors: {
+ base: :invalid_configuration,
+ is_admin: :true_or_false,
+ user: [ title: :blank, username: [:unique, :blank] ]
+ }
+ )
+ end
+ end
+end
+```
+
+Locale:
+```yaml
+en:
+ errors:
+ parameters:
+ invalid_configuration: 'Invalid configuration'
+ blank: '%{parameter} cannot be blank'
+ unique: '%{parameter} must be unique'
+
+ users:
+ is_admin:
+ true_or_false: 'must be true or false'
+ user:
+ username:
+ unique: 'Username has already been taken'
+```
+
+Metaractor will attempt to use the namespace of the code that reported the error.
+You can see that above with the `users` key in the locale.
+
+The i18n integration will walk its way from the most specific message to the least specific one, stopping at the first one it can find.
+We currently expose the following variables for use in the message:
+- `error_key`: the error we added (ex: `blank` or `invalid_configuration`)
+- `parameter`: the name of the parameter
+
+You can also use this feature to work with machine readable keys:
+```ruby
+result = Users::UpdateUser.call
+if result.failure? &&
+ result.errors[:is_admin] == :true_or_false
+
+ # handle this specific case
+end
+```
+
### Spec Helpers
Enable the helpers and/or matchers:
```ruby
RSpec.configure do |config|
config.include Metaractor::Spec::Helpers
@@ -219,12 +298,12 @@
).at_path(:user, :username)
expect(result).to include_errors('user.title cannot be blank')
```
-### Error Output
-Metaractor customizes the exception message for `Interactor::Failure`:
+### Hash Formatting
+Metaractor customizes the output for `Metaractor::Errors#inspect` and `Interactor::Failure`:
```
Interactor::Failure:
Errors:
{:base=>"NOPE"}
@@ -233,13 +312,15 @@
Context:
{:parent=>true, :chained=>true}
```
-You can further customize the exception message:
+You can further customize the hash formatting:
```ruby
-# Configure FailureOutput to use awesome_print
-Metaractor::FailureOutput.hash_formatter = ->(hash) { hash.ai }
+Metaractor.configure do |config|
+ # Configure Metaractor to use awesome_print
+ config.hash_formatter = ->(hash) { hash.ai }
+end
```
### Further Reading
For more examples of all of the above approaches, please see the specs.