Skip to content

Commit

Permalink
Refine documentation. Part 2 (#103)
Browse files Browse the repository at this point in the history
* Fix enumerations
* Refine the rest of the documentation
  • Loading branch information
Jaroslav Toropygin authored Apr 5, 2023
1 parent 349edb5 commit 6e1f1bc
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 144 deletions.
40 changes: 27 additions & 13 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ end
```

There are several ways to execute a recently defined business action, including `#perform`, `#perform!`, or `try_perform!`:

1. `perform!` raises an exception when encountering errors.
1. `perform` returns `false` when encountering errors.
1. `try_perform!` is comparable to `perform!` but doesn't execute the action if preconditions are not met.

2. `perform` returns `false` when encountering errors.

3. `try_perform!` is comparable to `perform!` but doesn't execute the action if preconditions are not met.

### Transactions

Expand Down Expand Up @@ -188,7 +191,7 @@ The behavior of the attributes is similar to that of `Granite::Form` objects, wi

With Granite Form objects, when a model attribute is exposed via `represents` and the Active Record object changes, the exposed attribute is immediately updated.

_In contrast_, Granite Actions use `assign_data` to update the represented attribute.
_In contrast_, Granite actions use `assign_data` to update the represented attribute.

#### Assigning the data

Expand Down Expand Up @@ -247,9 +250,12 @@ validates :subaction, nested: true
### Subject

The definition of the subject does three things:

1. Defines a `references_one` association.
1. Aliases its methods to common names (`subject` and `subject_id`)
1. Modifies the action initializer to provide the ability to pass the subject as the first argument and restricts subject-less action initialization.

2. Aliases its methods to common names (`subject` and `subject_id`)

3. Modifies the action initializer to provide the ability to pass the subject as the first argument and restricts subject-less action initialization.

Let's take a look to an example below:

Expand Down Expand Up @@ -289,9 +295,12 @@ Notice that the method `#user` has been assigned to the alias `#subject`, and `#
### Policies, preconditions, and validations

When deciding how to structure policies, preconditions, and validations, there are some simple rules to follow:

1. If the condition depends on _any user-provided attribute values_ except for the subject, it is a **validation**.
1. If the condition depends on _the subject or any value that depends on the subject_, it is a **precondition**.
1. Otherwise, if it is _related to the performer_, choose a **policy**.

2. If the condition depends on _the subject or any value that depends on the subject_, it is a **precondition**.

3. Otherwise, if it is _related to the performer_, choose a **policy**.

#### Policies

Expand All @@ -309,9 +318,12 @@ end
There is also an `allow_self` method that is equivalent to `allow_if { performer == subject }`, which allows an action to be performed by the subject itself.

Granite policies also support strategies:

1. By default, the [`AnyStrategy`](https://github.com/toptal/granite/blob/master/lib/granite/action/policies/any_strategy.rb) is used, which allows an action to be performed if any policy allows it.
1. Other built-in strategies include [`AlwaysAllowStrategy`](https://github.com/toptal/granite/blob/master/lib/granite/action/policies/always_allow_strategy.rb), which allows all actions,
1. And [`RequiredPerformerStrategy`](https://github.com/toptal/granite/blob/master/lib/granite/action/policies/required_performer_strategy.rb), which requires that a performer be present for all actions.

2. Other built-in strategies include [`AlwaysAllowStrategy`](https://github.com/toptal/granite/blob/master/lib/granite/action/policies/always_allow_strategy.rb), which allows all actions,

3. And [`RequiredPerformerStrategy`](https://github.com/toptal/granite/blob/master/lib/granite/action/policies/required_performer_strategy.rb), which requires that a performer be present for all actions.

You can also write your own custom policy strategy.

Expand Down Expand Up @@ -469,11 +481,13 @@ Here are some examples of using the rails g granite command:

This command generates a new action called "create" for the "user" `subject`. It creates three files: `apq/actions/ba/user/create.rb`, `apq/actions/ba/user/business_action.rb`, and `spec/apq/actions/ba/user/create_spec.rb`.

1. `rails g granite user/create -C`
Adding the `-C` option generates a collection action where the subject is not known at initialization. This command generates two files: `apq/actions/ba/user/create.rb` and `spec/apq/actions/ba/user/create_spec.rb`.
2. `rails g granite user/create -C`

Adding the `-C` option generates a collection action where the subject is not known at initialization. This command generates two files: `apq/actions/ba/user/create.rb` and `spec/apq/actions/ba/user/create_spec.rb`.

3. `rails g granite user/create simple`

1. `rails g granite user/create simple`
Adding a second argument, such as "simple" specifies the name of the projector to use. This command generates a new directory called simple within the `apq/actions/ba/user/create directory`, as well as the same files as the first example: `apq/actions/ba/user/create.rb`, `apq/actions/ba/user/business_action.rb`, and `spec/apq/actions/ba/user/create_spec.rb`.
Adding a second argument, such as "simple" specifies the name of the projector to use. This command generates a new directory called simple within the `apq/actions/ba/user/create directory`, as well as the same files as the first example: `apq/actions/ba/user/create.rb`, `apq/actions/ba/user/business_action.rb`, and `spec/apq/actions/ba/user/create_spec.rb`.

## Conclusion

Expand Down
Loading

0 comments on commit 6e1f1bc

Please sign in to comment.