README.md in tram-policy-0.0.1 vs README.md in tram-policy-0.0.2
- old
+ new
@@ -170,10 +170,40 @@
rescue Tram::Policy::ValidationError => error
error.policy == policy # => true
end
```
+## Additional options
+
+Class method `.validate` supports several options:
+
+### `stop_on_faiure`
+
+If a selected validation will fail (adds an error to the collection), the following validations won't be executed.
+
+```ruby
+require "tram-policy"
+
+class Article::ReadinessPolicy < Tram::Policy
+ # required param for article to validate
+ param :article
+
+ validate :title_presence, stop_on_failure: true
+ validate :title_valid # not executed if title is absent
+
+ # ...
+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.
@@ -195,11 +225,11 @@
end
```
```ruby
# spec/spec_helper.rb
-require "tram-policy/matcher"
+require "tram/policy/rspec"
```
```ruby
# spec/policies/user/readiness_policy_spec.rb
RSpec.describe User::ReadinessPolicy do
@@ -215,84 +245,111 @@
expect { policy }.not_to be_invalid_at level: "info"
end
end
```
-**Notice** that you have to wrap policy into block `{ policy }`. This is because matcher checks not only presence of an error, but also ensures its message is translated to all available locales (`I18n.available_locales`). The block containing a policy will be executed separately for every such language.
+**Notice** that you have to wrap policy into block `{ policy }`. This is because the matcher checks not only presence of an error, but also ensures its message is translated to all available locales (`I18n.available_locales`). The block containing a policy will be executed separately for every such language.
## Generators
The gem provides simple tool for scaffolding new policy along with RSpec test template.
```shell
-$ tram-policy user/readiness_policy -p user -o admin -v name_present email_present
+$ tram-policy user/readiness_policy -p user -o admin -v name_present:blank_name email_present:blank_email
```
This will generate a policy class with specification compatible to both [RSpec][rspec] and [FactoryGirl][factory-girl]:
```ruby
# app/policies/user/readiness_policy.rb
+
+# TODO: describe the policy, its subject and context
class User::ReadinessPolicy < Tram::Policy
+ # TODO: add default values (default: -> { ... }),
+ # coercers (type: proc(&:to_s)),
+ # and optional arguments (optional: true)
+ # when necessary
param :user
option :admin
validate :name_present
validate :email_present
private
def name_present
- return if true # modify condition
- errors.add :name_present # add necessary tags
+ # TODO: define a condition
+ return if true
+ # TODO: add necessary tags
+ errors.add :blank_name
end
def email_present
- return if true # modify condition
- errors.add :email_present # add necessary tags
+ # TODO: define a condition
+ return if true
+ # TODO: add necessary tags
+ errors.add :blank_email
end
end
```
```yaml
# config/tram-policies.en.yml
---
en:
user/readiness_policy:
- name_present: name_present
- email_present: email_present
+ blank_name: translation missing
+ blank_email: translation missing
```
```ruby
# spec/policies/user/readiness_policy_spec.rb
-RSpec.describe User::ReadinessPolicy do
- let(:user) { build :user } # <- expected a factory
+require "spec_helper"
+# TODO: move it to spec_helper
+require "tram/policy/rspec"
- subject(:policy) { described_class[user] }
+RSpec.describe User::ReadinessPolicy, ".[]" do
+ # TODO: either remove this line, or set another source for locales to check
+ let(:available_locales) { I18n.available_locales }
+ let(:user) { FactoryGirl.build :user }
- it { is_expected.to be_valid }
+ it "is valid with proper arguments" do
+ expect { described_class[user] }.to be_valid
+ end
+ # TODO: check the description
it "is invalid when not name_present" do
- policy # modify it correspondingly
- expect { policy }.to be_invalid_at # add tags to check
+ # TODO: modify some arguments
+ user = nil
+ # TODO: add necessary tags to focus the condition
+ expect { described_class[user] }.to be_invalid_at
end
+ # TODO: check the description
it "is invalid when not email_present" do
- policy # modify it correspondingly
- expect { policy }.to be_invalid_at # add tags to check
+ # TODO: modify some arguments
+ user = nil
+ # TODO: add necessary tags to focus the condition
+ expect { described_class[user] }.to be_invalid_at
end
end
```
-Later you can copy-paste that contexts to provide more edge case for testing your policies.
+Then you should go through all TODO-s and add necessary details.
+Later you can copy-paste examples to provide more edge case for testing your policies.
+
Notice that RSpec matcher `be_invalid_at` checks at once:
- that an error is added to the policy
- that the error has given tags
- that the error is translated to every available locale
-and provides full description for the essence of the failure.
+Its negation (`not_to be_invalid_at`) checks that no errors added with given tags.
+When called without tags, it checks that the policy is valid as a whole.
+
+Both matchers provide a full description for the essence of the failure.
## To Recap
The `Tram::Policy` DSL provides the following methods: