Readme.md in use_case-0.7.0 vs Readme.md in use_case-0.8.0
- old
+ new
@@ -44,14 +44,16 @@
# ...
def create
outcome = CreateRepository.new(self, current_user).execute(params)
- outcome.pre_condition_failed do |condition|
- redirect_to(login_path) and return if condition.is_a?(UserLoggedInPrecondition)
- flash[:error] = "You're not allowed to do that"
- redirect_to project_path
+ outcome.pre_condition_failed do |f|
+ f.when(:user_required) { redirect_to(login_path) }
+ f.otherwise do
+ flash[:error] = "You're not allowed to do that"
+ redirect_to project_path
+ end
end
outcome.failure do |model|
# Render form with validation errors
render :new, :locals => { :repository => model }
@@ -107,11 +109,11 @@
end
# This is often implemented as a controller filter in many Rails apps.
# Unfortunately that means we have to duplicate the check when exposing the use
# case in other contexts (e.g. a stand-alone API app, console API etc).
-class UserLoggedInPrecondition
+class UserRequired
# The constructor is only used by us and can look and do whever we want
def initialize(user)
@user = user
end
@@ -203,15 +205,82 @@
`Virtus` backed class as `input_class` you will get an instance of that class as
`params` in pre-conditions and commands.
## Pre-conditions
-A pre-condition is any object that responds to `satisfied?(params)` where
-params will either be a `Hash` or an instance of whatever you passed to
-`input_class`. The method should return `true/false`. If it raises, the outcome
-of the use case will call the `pre_condition_failed` block with the raised
-error. If it fails, the `pre_condition_failed` block will be called with the
-pre-condition instance that failed.
+A pre-condition is any object that responds to `satisfied?(params)` where params
+will either be a `Hash` or an instance of whatever you passed to `input_class`.
+The method should return `true/false`. If it raises, the outcome of the use case
+will call the `pre_condition_failed` block with the raised error. If it fails,
+the `pre_condition_failed` block will be called with a failure object wrapping
+the pre-condition instance that failed.
+
+The wrapper failure object provides three methods of interest:
+
+### `when`
+
+The when method allows you to associate a block of code with a specific
+pre-condition. The block is called with the pre-condition instance if that
+pre-condition fails. Because the pre-condition class may not be explicitly
+available in contexts where you want to use `when`, a symbolic representation is
+used.
+
+If you have the following two pre-conditions:
+
+* `UserRequired`
+* `ProjectAdminRequired`
+
+Then you can use `when(:user_required) { |condition ... }` and
+`when(:project_admin_required) { |condition ... }`. If you want control over how
+a class name is symbolized, make the class implement `symbol`, i.e.:
+
+```js
+class UserRequired
+ def self.symbol; :user_plz; end
+ def initialize(user); @user = user; end
+ def satisfied?(params); !@user.nil?; end
+end
+
+# Then:
+
+outcome = use_case.execute(params)
+
+outcome.pre_condition_failed do |f|
+ f.when(:user_plz) { |c| puts "Needs moar user" }
+ # ...
+end
+```
+
+### `otherwise`
+
+`otherwise` is a catch-all that is called if no calls to `when` mention the
+offending pre-condition:
+
+
+```js
+class CreateProject
+ include UseCase
+
+ def initialize(user)
+ add_pre_condition(UserRequired.new(user))
+ add_pre_condition(AdminRequired.new(user))
+ step(CreateProjectCommand.new(user))
+ end
+end
+
+# Then:
+
+outcome = CreateProject.new(current_user).execute(params)
+
+outcome.pre_condition_failed do |f|
+ f.when(:user_required) { |c| puts "Needs moar user" }
+ f.otherwise { |c| puts "#{c.name} pre-condition failed" }
+end
+```
+### `pre_condition`
+
+If you want to roll your own flow control, simply get the offending
+pre-condition from this method.
## Validations
The validator uses `ActiveModel::Validations`, so any Rails validation can go in
here (except for `validates_uniqueness_of`, which apparently comes from