README.md in tram-policy-0.1.1 vs README.md in tram-policy-0.2.0
- old
+ new
@@ -41,11 +41,11 @@
option :text, proc(&:to_s), default: -> { article.text }
# define what methods and in what order we should use to validate an article
validate :title_presence
validate :subtitle_presence
- validate :text_presence
+ validate { errors.add :empty, field: "text", level: "error" if text.empty? }
private
def title_presence
return unless title.empty?
@@ -57,17 +57,10 @@
def subtitle_presence
return unless subtitle.empty?
# Notice that we can set another level
errors.add "Subtitle is empty", field: "subtitle", level: "warning"
end
-
- def text_presence
- return unless text.empty?
- # Adds an error with a translated message. All fields are available
- # both as error tags, and I18n translation options
- errors.add :empty_text, field: "text", level: "error"
- end
end
```
Because validation is the only responsibility of a policy, we don't need to call it explicitly. Policy initializer will perform all the checks immediately, memoizing the results into `errors` array. The methods `#valid?`, `#invalid?` and `#validate!` just check those `#errors`.
@@ -124,40 +117,44 @@
private
def article_readiness
# Collects errors tagged by level: "error" from "nested" policy
- others = Article::ReadinessPolicy[article].errors.by_tags(level: "error")
+ readiness_errors = Article::ReadinessPolicy[article].errors.by_tags(level: "error")
# Merges collected errors to the current ones.
- # New errors are tagged by source: "readiness".
- # Notice the block takes _hashified_ errors.
- errors.merge(others) { |hash| hash[:source] = "readiness" }
+ # New errors are also tagged by source: "readiness".
+ errors.merge(readiness_errors, source: "readiness")
end
def article_selection
errors.add "Not selected", field: "selected", level: "info" unless selected
end
end
```
-As mentioned above, sending a symbolic key to the `errors#add` means the key should be translated by [I18n][i18n]. The only magic under the hood is that a scope for the translation is taken from the full name of current class. All tags are available as options:
+As mentioned above, sending a symbolic key to the `errors#add` means the key should be translated by [I18n][i18n]. The only magic under the hood concerns a scope for the translation. By default it is taken from the full name of current class prepended with `"evil.client.errors"`.
+> You can redefine the scope by reloading private method `.scope` of the policy.
+
+All tags are available as options:
+
```ruby
class Article::PublicationPolicy < Tram::Policy
# ...
- errors.add :empty_text, field: "text", level: "error"
+ errors.add :empty, field: "text", level: "error"
# ...
end
```
```yaml
# /config/locales/en.yml
---
en:
- article/publication_policy:
- empty_text: "Validation %{level}: %{field} is empty"
+ tram-policy:
+ article/publication_policy:
+ empty: "Validation %{level}: %{field} is empty"
```
This will provide error message "Validation error: text is empty".
The last thing to say is about exceptions. When you use `validate!` it raises `Tram::Policy::ValidationError` (subclass of `RuntimeError`). Its message is built from selected errors (taking into account a `validation!` filter).
@@ -192,18 +189,10 @@
# ...
end
```
-### `if`
-
-[WIP] Not implemented (coming soon in v0.1.0)
-
-### `unless`
-
-[WIP] Not implemented (coming soon in v0.1.0)
-
## RSpec matchers
RSpec matchers defined in a file `tram-policy/matcher` (not loaded in runtime).
Use `be_invalid_at` matcher to check whether a policy has errors with given tags.
@@ -295,12 +284,13 @@
```yaml
# config/tram-policies.en.yml
---
en:
- user/readiness_policy:
- blank_name: translation missing
- blank_email: translation missing
+ tram-policy:
+ user/readiness_policy:
+ blank_name: translation missing
+ blank_email: translation missing
```
```ruby
# spec/policies/user/readiness_policy_spec.rb
require "spec_helper"