bullet_train 1.0.89 → 1.0.93
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/models/concerns/memberships/base.rb +0 -1
- data/app/views/layouts/docs.html.erb +6 -0
- data/docs/action-models.md +148 -0
- data/docs/index.md +1 -0
- data/lib/bullet_train/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0fd0ed98cb437a6a91f7289ee15c050bbf07ad8321c2eb5cd62e6095bc58b67e
|
4
|
+
data.tar.gz: 7f380b03457f3a8f68d87451a731c7dc0c3c67fbfe1de2ac9bc0984f5a6e5075
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b56c26291a63a669de8526e03b60473ea44589f562efb85ba0e100c8267b9d8b1e6b728acb1fcfe71b97a0f9789d5e24451b04a2609ab9e7f9941970195825d9
|
7
|
+
data.tar.gz: 95a757e8187c5b0d0f0108794796b1b73a2d8f8b3edccf20c9040b6e6308ba594f650b73cb5576f41080dcd9f9bc34a154a2de8b9bbd106858a81bd347cfa59d
|
@@ -13,7 +13,6 @@ module Memberships::Base
|
|
13
13
|
|
14
14
|
has_many :scaffolding_completely_concrete_tangible_things_assignments, class_name: "Scaffolding::CompletelyConcrete::TangibleThings::Assignment", dependent: :destroy
|
15
15
|
has_many :scaffolding_completely_concrete_tangible_things, through: :scaffolding_completely_concrete_tangible_things_assignments, source: :tangible_thing
|
16
|
-
has_many :reassignments_scaffolding_completely_concrete_tangible_things_reassignments, class_name: "Memberships::Reassignments::ScaffoldingCompletelyConcreteTangibleThingsReassignment", dependent: :destroy, foreign_key: :membership_id
|
17
16
|
|
18
17
|
has_many :scaffolding_absolutely_abstract_creative_concepts_collaborators, class_name: "Scaffolding::AbsolutelyAbstract::CreativeConcepts::Collaborator", dependent: :destroy
|
19
18
|
|
@@ -119,6 +119,12 @@
|
|
119
119
|
<% end %>
|
120
120
|
<% end %>
|
121
121
|
|
122
|
+
<%= render 'account/shared/menu/item', url: '/docs/action-models', label: 'Action Models' do |p| %>
|
123
|
+
<% p.content_for :icon do %>
|
124
|
+
<i class="fal fa-bars-progress ti ti-target"></i>
|
125
|
+
<% end %>
|
126
|
+
<% end %>
|
127
|
+
|
122
128
|
<%= render 'account/shared/menu/item', url: '/docs/seeds', label: 'Database Seeds' do |p| %>
|
123
129
|
<% p.content_for :icon do %>
|
124
130
|
<i class="fal fa-seedling ti ti-server"></i>
|
@@ -0,0 +1,148 @@
|
|
1
|
+
# Action Models
|
2
|
+
|
3
|
+
Action Models make it easy to scaffold and implement user-facing custom actions in your Bullet Train application and API in a RESTful way. Action Models are perfect for situations where you want one or more of the following:
|
4
|
+
|
5
|
+
- Bulk actions for a model where users can select one or more objects as targets.
|
6
|
+
- Long-running background tasks where you want to keep users updated on their progress in the UI or notify then after completion.
|
7
|
+
- Actions that have one or more configuration options available.
|
8
|
+
- Tasks that can be configured now but scheduled to take place later.
|
9
|
+
- Actions where you want to keep an in-app record of when it happened and who initiated the action.
|
10
|
+
- Tasks that one team member can initiate, but a team member with elevated privileges has to approve.
|
11
|
+
|
12
|
+
Examples of real-world features that can be easily implemented using Action Models include:
|
13
|
+
|
14
|
+
- A project manager can archive multiple projects at once.
|
15
|
+
- A customer service agent can refund multiple payments at once and provide a reason.
|
16
|
+
- A user can see progress updates while their 100,000 row CSV file is imported.
|
17
|
+
- A marketing manager can publish a blog post now or schedule it for publication tomorrow at 9 AM.
|
18
|
+
- A contributor can propose a content template change that will be applied after review and approval.
|
19
|
+
|
20
|
+
Importantly, Action Models aren't a special new layer in your application or a special section of your code base. Instead, they're just regular models, with corresponding scaffolded views and controllers, that exist alongside the rest of your domain model. They leverage Bullet Train's existing strengths around domain modeling and code generation with Super Scaffolding.
|
21
|
+
|
22
|
+
They're also super simple and very DRY. Consider the following example, assuming the process of archiving each project is very complicated and takes a lot of time:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
class Projects::ArchiveAction < ApplicationRecord
|
26
|
+
include Actions::TargetsMany
|
27
|
+
include Actions::ProcessesAsync
|
28
|
+
include Actions::HasProgress
|
29
|
+
include Actions::CleansUp
|
30
|
+
|
31
|
+
belongs_to :team
|
32
|
+
|
33
|
+
def valid_targets
|
34
|
+
team.projects
|
35
|
+
end
|
36
|
+
|
37
|
+
def perform_on_target(project)
|
38
|
+
project.archive
|
39
|
+
end
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
## Installation
|
44
|
+
|
45
|
+
### 1. Purchase Bullet Train Pro
|
46
|
+
|
47
|
+
First, [purchase Bullet Train Pro](https://buy.stripe.com/aEU7vc4dBfHtfO89AV). Once you've completed this process, you'll be issued a private token for the Bullet Train Pro package server. The process is currently completed manually, so you may have to way a little to receive your keys.
|
48
|
+
|
49
|
+
### 2. Install the Package
|
50
|
+
|
51
|
+
You'll need to specify both Ruby gems in your `Gemfile`, since we have to specify a private source for both:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
source "https://YOUR_TOKEN_HERE@gem.fury.io/bullettrain" do
|
55
|
+
gem "bullet_train-action_models"
|
56
|
+
end
|
57
|
+
```
|
58
|
+
|
59
|
+
Don't forget to run `bundle install` and `rails restart`.
|
60
|
+
|
61
|
+
## Super Scaffolding Commands
|
62
|
+
|
63
|
+
You can get detailed information about using Super Scaffolding to generate different types of Action Models like so:
|
64
|
+
|
65
|
+
```
|
66
|
+
bin/super-scaffold action-model:targets-many
|
67
|
+
bin/super-scaffold action-model:targets-one
|
68
|
+
bin/super-scaffold action-model:targets-one-parent
|
69
|
+
```
|
70
|
+
|
71
|
+
## Basic Example
|
72
|
+
|
73
|
+
### 1. Generate and scaffold an example `Project` model.
|
74
|
+
|
75
|
+
```
|
76
|
+
rails g model Project team:references name:string
|
77
|
+
bin/super-scaffold crud Project Team name:text_field
|
78
|
+
```
|
79
|
+
|
80
|
+
### 2. Generate and scaffold an archive action for projects.
|
81
|
+
|
82
|
+
```
|
83
|
+
bin/super-scaffold action-model:targets-many Archive Project Team
|
84
|
+
```
|
85
|
+
|
86
|
+
### 3. Implement the action logic.
|
87
|
+
|
88
|
+
Open `app/models/projects/archive_action.rb` and update the implementation of this method:
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
def perform_on_target(project)
|
92
|
+
project.archive
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
96
|
+
You're done!
|
97
|
+
|
98
|
+
## Additional Examples
|
99
|
+
|
100
|
+
### Add configuration options to an action.
|
101
|
+
|
102
|
+
Because Action Models are just regular models, you can add new fields to them with Super Scaffolding the same as any other model. This is an incredible strength, because it means the configuration options for your Action Models can leverage the entire suite of form field types available in Bullet Train, and maintaining the presentation of those options to users is like maintaining any other model form in your application.
|
103
|
+
|
104
|
+
For example:
|
105
|
+
|
106
|
+
```
|
107
|
+
rails g migration add notify_users_to_projects_archive_actions notify_users:boolean
|
108
|
+
# side quest: update the generated migration with `default: false` on the new boolean field.
|
109
|
+
bin/super-scaffold crud-field Projects::ArchiveAction notify_users:boolean
|
110
|
+
```
|
111
|
+
|
112
|
+
Now users will be prompted with that option when they perform this action, and you can update your logic to take action based on it, or at least pass on the information to another method that takes action based on it:
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
def perform_on_target(project)
|
116
|
+
project.archive(send_notification: notify_users)
|
117
|
+
end
|
118
|
+
```
|
119
|
+
|
120
|
+
## Action Types
|
121
|
+
|
122
|
+
Action Models can be generated in three flavors:
|
123
|
+
|
124
|
+
- `action-model:targets-many`
|
125
|
+
- `action-model:targets-one`
|
126
|
+
- `action-model:targets-one-parent`
|
127
|
+
|
128
|
+
### Targets Many
|
129
|
+
|
130
|
+
Action Models that _can_ target many objects are by far the most common, but it's important to understand that they're not only presented to users as bulk actions. Instead, by default, they're presented to users as an action available for each individual object, but they're also presented as a bulk action when users have selected multiple objects.
|
131
|
+
|
132
|
+
"Targets many" actions live at the same level in the domain model (and belong to the same parent) as the model they target. (If this doesn't make immediate sense, just consider that it would be impossible for instances of these actions to live under multiple targets at the same time.)
|
133
|
+
|
134
|
+
### Targets One
|
135
|
+
|
136
|
+
Sometimes you have an action that will only ever target one object at a time. In this case, they're generated a little differently and live under (and belong to) the model they target.
|
137
|
+
|
138
|
+
When deciding between "targets many" and "targets one", our recommendation is that you only use "targets one" for actions that you know for certain could never make sense targeting more than one object at the same time. For example, if you're creating a send action for an email that includes configuration options and scheduling details, you may be reasonably confident that you never need users to be able to schedule two different emails at the same time with the same settings. That would be a good candidate for a "targets one" action.
|
139
|
+
|
140
|
+
### Targets One Parent
|
141
|
+
|
142
|
+
This final type of action is available for things like importers that don't necessarily target specific existing objects by ID, but instead create many new or affect many existing objects under a specific parent based on the configuration of the action (like an attached CSV file.) These objects don't "target many" per se, but they live at the same level (and belong to the same parent) as the models they end up creating or affecting.
|
143
|
+
|
144
|
+
## Frequently Asked Questions
|
145
|
+
|
146
|
+
### Do Action Models have to be persisted to the database?
|
147
|
+
|
148
|
+
No. Action Models extend from `ApplicationRecord` by default, but if you're not using features that depend on persistence to the database, you can make them `include ActiveModel::API` instead. That said, it's probably not worth the trouble. As an alternative, consider just including `Actions::CleansUp` in your action to ensure it removes itself from the database after completion.
|
data/docs/index.md
CHANGED
@@ -16,6 +16,7 @@
|
|
16
16
|
|
17
17
|
## Developer Tools
|
18
18
|
- [Super Scaffolding](/docs/super-scaffolding.md)
|
19
|
+
- [Action Models](/docs/action-models.md)
|
19
20
|
- [Database Seeds](/docs/seeds.md)
|
20
21
|
- [Test Suite](/docs/testing.md)
|
21
22
|
- [Point-and-Click Test Writing](https://github.com/bullet-train-co/magic_test) <i class="ti ti-new-window ml-2"></i>
|
data/lib/bullet_train/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bullet_train
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.93
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Culver
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-07-
|
11
|
+
date: 2022-07-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: standard
|
@@ -607,6 +607,7 @@ files:
|
|
607
607
|
- db/migrate/20210816072508_add_locale_to_teams.rb
|
608
608
|
- db/migrate/20211020200855_add_doorkeeper_application_to_memberships.rb
|
609
609
|
- db/migrate/20211027002944_add_doorkeeper_application_to_users.rb
|
610
|
+
- docs/action-models.md
|
610
611
|
- docs/api.md
|
611
612
|
- docs/authentication.md
|
612
613
|
- docs/billing/stripe.md
|