bullet_train 1.0.36 → 1.0.39
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/views/layouts/docs.html.erb +1 -1
- data/config/routes.rb +1 -1
- data/docs/api.md +3 -0
- data/docs/authentication.md +13 -0
- data/docs/billing/stripe.md +90 -0
- data/docs/desktop.md +13 -0
- data/docs/field-partials/buttons.md +42 -0
- data/docs/field-partials/super-select.md +58 -0
- data/docs/field-partials.md +132 -0
- data/docs/font-awesome-pro.md +50 -0
- data/docs/getting-started.md +55 -0
- data/docs/heroku.md +91 -0
- data/docs/i18n.md +3 -0
- data/docs/index.md +52 -0
- data/docs/indirection.md +3 -0
- data/docs/modeling.md +93 -0
- data/docs/namespacing.md +11 -0
- data/docs/oauth.md +27 -0
- data/docs/onboarding.md +41 -0
- data/docs/overriding.md +53 -0
- data/docs/permissions.md +18 -0
- data/docs/seeds.md +48 -0
- data/docs/super-scaffolding/delegated-types.md +328 -0
- data/docs/super-scaffolding.md +246 -0
- data/docs/teams.md +8 -0
- data/docs/testing.md +34 -0
- data/docs/themes.md +101 -0
- data/docs/tunneling.md +29 -0
- data/docs/upgrades.md +69 -0
- data/docs/webhooks/incoming.md +3 -0
- data/docs/webhooks/outgoing.md +3 -0
- data/lib/bullet_train/version.rb +1 -1
- metadata +30 -1
@@ -0,0 +1,246 @@
|
|
1
|
+
# Code Generation with Super Scaffolding
|
2
|
+
|
3
|
+
Super Scaffolding is Bullet Train’s code generation engine. Its goal is to allow you to produce production-ready CRUD interfaces for your models while barely lifting a finger, and it handles a lot of other grunt-work as well.
|
4
|
+
|
5
|
+
Here’s a list of what Super Scaffolding takes care of for you each time you add a model to your application:
|
6
|
+
|
7
|
+
- It generates a basic CRUD controller and accompanying views.
|
8
|
+
- It generates a Yaml locale file for the views’ translatable strings.
|
9
|
+
- It generates type-specific form fields for each attribute of the model.
|
10
|
+
- It generates an API controller and an accompanying entry in the application’s API docs.
|
11
|
+
- It generates a serializer that’s used by the API and when dispatching webhooks.
|
12
|
+
- It adds the appropriate permissions for multitenancy in CanCanCan’s configuration file.
|
13
|
+
- It adds the model’s table view to the show view of its parent.
|
14
|
+
- It adds the model to the application’s navigation (if applicable).
|
15
|
+
- It generates breadcrumbs for use in the application’s layout.
|
16
|
+
- It generates the appropriate routes for the CRUD controllers and API endpoints.
|
17
|
+
|
18
|
+
When adding just one model, Super Scaffolding generates ~30 different files on your behalf.
|
19
|
+
|
20
|
+
## Living Templates
|
21
|
+
|
22
|
+
Bullet Train's Super Scaffolding engine is a unique approach to code generation, based on template files that are functional code instead of obscure DSLs that are difficult to customize and maintain. Super Scaffolding automates the most repetitive and mundane aspects of building out your application's basic structure. Furthermore, it does this without leaning on the magic of libraries that force too high a level of abstraction. Instead, it generates standard Rails code that is both ready for prime time, but is also easy to customize and modify.
|
23
|
+
|
24
|
+
## Prerequisites
|
25
|
+
|
26
|
+
Before getting started with Super Scaffolding, we recommend reading about [the philosophy of domain modeling in Bullet Train](/docs/topics/domain-modeling.md).
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
The Super Scaffolding shell script provides its own documentation. If you're curious about specific scaffolders or parameters, you can run the following in your shell:
|
31
|
+
|
32
|
+
```
|
33
|
+
bin/super-scaffold
|
34
|
+
```
|
35
|
+
|
36
|
+
## Examples
|
37
|
+
|
38
|
+
### 1. Basic CRUD Scaffolding with `crud`
|
39
|
+
|
40
|
+
Let's implement the following feature:
|
41
|
+
|
42
|
+
> An organization has many projects.
|
43
|
+
|
44
|
+
First, generate the model with the standard Rails generator:
|
45
|
+
|
46
|
+
```
|
47
|
+
rails g model Project team:references name:string
|
48
|
+
```
|
49
|
+
|
50
|
+
In the above example, `team` represents the model that a `Project` primarily belongs to.
|
51
|
+
|
52
|
+
⚠️ Don't run migrations right away. It would be fine in this case, but sometimes the subsequent Super Scaffolding step actually updates the migration as part of its magic.
|
53
|
+
|
54
|
+
Next, run the `crud` scaffolder:
|
55
|
+
|
56
|
+
```
|
57
|
+
bin/super-scaffold crud Project Team name:text_field
|
58
|
+
rake db:migrate
|
59
|
+
```
|
60
|
+
|
61
|
+
In the above example, `text_field` was selected from [the list of available field partials](/docs/field-partials.md). We'll show examples with `trix_editor` and `super_select` later.
|
62
|
+
|
63
|
+
### 2. Nested CRUD Scaffolding with `crud`
|
64
|
+
|
65
|
+
Building on that example, let's implement the following feature:
|
66
|
+
|
67
|
+
```
|
68
|
+
A project has many goals.
|
69
|
+
```
|
70
|
+
|
71
|
+
Again, we'll generate the model using the standard Rails generator:
|
72
|
+
|
73
|
+
```
|
74
|
+
rails g model Goal project:references description:string
|
75
|
+
```
|
76
|
+
|
77
|
+
You can see in the example above that there is no direct reference to team, but to `project` instead, since that's where a `Goal` belongs.
|
78
|
+
|
79
|
+
Now, run the `crud` scaffolder:
|
80
|
+
|
81
|
+
```
|
82
|
+
bin/super-scaffold crud Goal Project,Team description:text_field
|
83
|
+
rake db:migrate
|
84
|
+
```
|
85
|
+
|
86
|
+
You can see in the example above how we've specified `Project,Team`, because we want to specify the entire chain of ownership back to the `Team`. This allows Super Scaffolding to automatically generate the required permissions.
|
87
|
+
|
88
|
+
### 3. Adding New Fields with `crud-field`
|
89
|
+
|
90
|
+
One of Bullet Train's most valuable features is the ability to add new fields to existing scaffolded models. When you add new fields with the `crud-field` scaffolder, you don't have to remember to add that same attribute to table views, show views, translation files, API endpoints, serializers, tests, documentation, etc.
|
91
|
+
|
92
|
+
Building on the earlier example, consider the following new requirement:
|
93
|
+
|
94
|
+
> In addition to a name, a project can have a description.
|
95
|
+
|
96
|
+
First, use the standard Rails migration generator to add the attribute in the database:
|
97
|
+
|
98
|
+
```
|
99
|
+
rails g migration add_description_to_projects description:text
|
100
|
+
```
|
101
|
+
|
102
|
+
Then, use the `crud-field` scaffolder to add it throughout the application:
|
103
|
+
|
104
|
+
```
|
105
|
+
bin/super-scaffold crud-field Project description:trix_editor
|
106
|
+
rake db:migrate
|
107
|
+
```
|
108
|
+
|
109
|
+
As you can see, when we're using `crud-field`, we don't need to supply the chain of ownership back to `Team`.
|
110
|
+
|
111
|
+
### 4. Adding Option Fields with Fixed, Translatable Options
|
112
|
+
|
113
|
+
Continuing with the earlier example, let's address the following new requirement:
|
114
|
+
|
115
|
+
> Users can specify the current project status.
|
116
|
+
|
117
|
+
We have multiple [field partials](/docs/field-partials.md) that we could use for this purpose, including `buttons`, `options`, or `super_select`.
|
118
|
+
|
119
|
+
In this example, let's add a status attribute and present it as buttons:
|
120
|
+
|
121
|
+
```
|
122
|
+
rails g migration add_status_to_projects status:string
|
123
|
+
bin/super-scaffold crud-field Project status:buttons
|
124
|
+
```
|
125
|
+
|
126
|
+
By default, Super Scaffolding configures the buttons as "One", "Two", and "Three", but in this example you can edit those options in the `fields` section of `config/locales/en/projects.en.yml`. For example, you could specify the following options:
|
127
|
+
|
128
|
+
```
|
129
|
+
planned: Planned
|
130
|
+
started: Started
|
131
|
+
completed: Completed
|
132
|
+
```
|
133
|
+
|
134
|
+
If you want new `Project` models to be set to `planned` by default, you can add that to the migration file that was generated before running it, like so:
|
135
|
+
|
136
|
+
```
|
137
|
+
add_column :projects, :status, :string, default: "planned"
|
138
|
+
```
|
139
|
+
|
140
|
+
### 5. Scaffolding `belongs_to` Associations, Team Member Assignments
|
141
|
+
|
142
|
+
Continuing with the example, consider the following requirement:
|
143
|
+
|
144
|
+
> A project has one specific project lead.
|
145
|
+
|
146
|
+
Although you might think this calls for a reference to `User`, we've learned the hard way that it's typically much better to assign resources on a `Team` to a `Membership` on the team instead. For one, this allows you to assign resources to new team members that haven't accepted their invitation yet (and don't necessarily have a `User` record yet.)
|
147
|
+
|
148
|
+
We can accomplish this like so:
|
149
|
+
|
150
|
+
```
|
151
|
+
rails g migration add_lead_to_projects lead:references
|
152
|
+
```
|
153
|
+
|
154
|
+
Then, to add the field, we specify the following:
|
155
|
+
|
156
|
+
```
|
157
|
+
bin/super-scaffold crud-field Project lead_id:super_select[class_name=Membership]
|
158
|
+
rake db:migrate
|
159
|
+
```
|
160
|
+
|
161
|
+
There are two important things to point out here:
|
162
|
+
|
163
|
+
1. When we use `rails g model` or `rails g migration`, we specify the `references` column name as `lead`, but when we're specifying the _field_ we want to scaffold, we specify it as `lead_id`, because that's the name of the attribute on the form, in strong parameters, etc.
|
164
|
+
2. We have to specify the model name with the `class_name` option so that Super Scaffolding can fully work it's magic. We can't reflect on the association, because at this point the association isn't properly defined yet. With this information, Super Scaffolding can handle that step for you.
|
165
|
+
|
166
|
+
Finally, Super Scaffolding will prompt you to edit `app/models/project.rb` and implement the required logic in the `valid_leads` method. This is a template method that will be used to both populate the select field on the `Project` form, but also enforce some important security concerns in this multi-tenant system. In this case, you can define it as:
|
167
|
+
|
168
|
+
```
|
169
|
+
def valid_leads
|
170
|
+
team.memberships.current_and_invited
|
171
|
+
end
|
172
|
+
```
|
173
|
+
|
174
|
+
(The `current_and_invited` scope just filters out people that have already been removed from the team.)
|
175
|
+
|
176
|
+
### 6. Scaffolding Has-Many-Through Associations with `join-model`
|
177
|
+
|
178
|
+
Finally, working from the same example, imagine the following requirement:
|
179
|
+
|
180
|
+
> A project can be labeled with one or more project-specific tags.
|
181
|
+
|
182
|
+
We can accomplish this with a new model, a new join model, and a `super_select` field.
|
183
|
+
|
184
|
+
First, let's create the tag model:
|
185
|
+
|
186
|
+
```
|
187
|
+
rails g model Projects::Tag team:references name:string
|
188
|
+
bin/super-scaffold crud Projects::Tag Team name:text_field
|
189
|
+
```
|
190
|
+
|
191
|
+
Note that project tags are specifically defined at the `Team` level. The same tag can be applied to multiple `Project` models.
|
192
|
+
|
193
|
+
Now, let's create a join model for the has-many-through association:
|
194
|
+
|
195
|
+
```
|
196
|
+
rails g model Projects::AppliedTag project:references tag:references
|
197
|
+
```
|
198
|
+
|
199
|
+
We're not going to scaffold this model with the typical `crud` scaffolder, but some preparation is needed before we can use it with the `crud-field` scaffolder, so we need to do the following:
|
200
|
+
|
201
|
+
```
|
202
|
+
bin/super-scaffold join-model Projects::AppliedTag project_id[class_name=Project] tag_id[class_name=Projects::Tag]
|
203
|
+
```
|
204
|
+
|
205
|
+
All we're doing here is specifying the name of the join model, and the two attributes and class names of the models it joins. Note again that we specify the `_id` suffix on both of the attributes.
|
206
|
+
|
207
|
+
Now that the join model has been prepared, we can use the `crud-field` scaffolder to create the multi-select field:
|
208
|
+
|
209
|
+
```
|
210
|
+
bin/super-scaffold crud-field Project tag_ids:super_select[class_name=Projects::Tag]
|
211
|
+
rake db:migrate
|
212
|
+
```
|
213
|
+
|
214
|
+
Just note that the suffix of the field is `_ids` plural, and this is an attribute provided by Rails to interact with the `has_many :tags, through: :applied_tags` association.
|
215
|
+
|
216
|
+
The `crud-field` step will ask you to define the logic for the `valid_tags` method in `app/models/project.rb`. You can define it like so:
|
217
|
+
|
218
|
+
```
|
219
|
+
def valid_tags
|
220
|
+
team.projects_tags
|
221
|
+
end
|
222
|
+
```
|
223
|
+
|
224
|
+
Honestly, it's crazy that we got to the point where we can handle this particular use case automatically. It seems simple, but there is so much going on to make this feature work.
|
225
|
+
|
226
|
+
## Additional Notes
|
227
|
+
|
228
|
+
### `TangibleThing` and `CreativeConcept`
|
229
|
+
|
230
|
+
In order to properly facilitate this type of code generation, Bullet Train includes two models in the `Scaffolding` namespace:
|
231
|
+
|
232
|
+
1. `Scaffolding::AbsolutelyAbstract::CreativeConcept`
|
233
|
+
2. `Scaffolding::CompletelyConcrete::TangibleThing`
|
234
|
+
|
235
|
+
Their peculiar naming is what's required to ensure that their corresponding view and controller templates can serve as the basis for any combination of different model naming or [namespacing](https://blog.bullettrain.co/rails-model-namespacing/) that you may need to employ in your own application.
|
236
|
+
|
237
|
+
### Hiding Scaffolding Templates
|
238
|
+
|
239
|
+
You won't want your end users seeing the Super Scaffolding templates in your environment, so you can disable their presentation by setting `HIDE_THINGS` in your environment. For example, you can add the following to `config/application.yml`:
|
240
|
+
|
241
|
+
```
|
242
|
+
HIDE_THINGS: true
|
243
|
+
```
|
244
|
+
|
245
|
+
## Advanced Examples
|
246
|
+
- [Super Scaffolding with Delegated Types](/docs/super-scaffolding/delegated-types.md)
|
data/docs/teams.md
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# Teams
|
2
|
+
|
3
|
+
Please read the article providing [an overview of organizational teams in Bullet Train](https://blog.bullettrain.co/teams-should-be-an-mvp-feature/). This article doesn't just explain how `Team`, `Membership`, `Invitation` and `Role` relate and function in Bullet Train, but it also explains how to properly think about resource ownership even in complex scenarios. Furthermore, it touches on ways in which Bullet Train's organizational structure has been successfully extended in more complicated systems.
|
4
|
+
|
5
|
+
Rather than simply duplicating the content of that blog article here, we'll focus on keeping that article up-to-date so it can benefit not only incoming Bullet Train developers, but also the broader developer ecosystem.
|
6
|
+
|
7
|
+
## Related Topics
|
8
|
+
- [Permissions](/docs/permissions.md)
|
data/docs/testing.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# Automated Test Suite
|
2
|
+
All of Bullet Train’s core functionality is verifiable using the provided test suite. This foundation of headless browser integration tests took a ton of time to write, but they can give you the confidence and peace of mind that you haven't broken any key functionality in your application before a deploy.
|
3
|
+
|
4
|
+
You can run the test suite with the following command in your shell:
|
5
|
+
|
6
|
+
```
|
7
|
+
rails test:system
|
8
|
+
```
|
9
|
+
|
10
|
+
## Fixing Broken Tests
|
11
|
+
|
12
|
+
### 1. Run Chrome in Non-Headless Mode
|
13
|
+
|
14
|
+
When debugging tests, it's important to be able to see what Capybara is seeing. You can disable the headless browser mode by prefixing `rails test` like so:
|
15
|
+
|
16
|
+
```
|
17
|
+
MAGIC_TEST=1 rails test
|
18
|
+
```
|
19
|
+
|
20
|
+
When you run the test suite with `MAGIC_TEST` set in your environment like this, the browser will appear on your screen after the first Capybara test starts. (This may not be the first test that runs.) Be careful not to interact with the window when it appears, as sometimes your interactions can cause the test to fail needlessly.
|
21
|
+
|
22
|
+
### 2. Insert `binding.pry`.
|
23
|
+
|
24
|
+
Open the failing test file and insert `binding.pry` right before the action or assertion that is causing the test to fail. After doing that, when you run the test, it will actually stop and open a debugging console while the browser is still open to the appropriate page where the test is beginning to fail. You can use this console and the open browser to try and figure out why the test is failing. When you're done, hit <kbd>Control</kbd> + <kbd>D</kbd> to exit the debugger and continue letting the test run.
|
25
|
+
|
26
|
+
## Super Scaffolding Test Suite
|
27
|
+
In addition to the standard application test suite, there is a separate test available that doesn't run by default that you can run in CI to ensure you haven't accidentally broken the full function of Super Scaffolding in your application. Before the test runs, there is a setup script that runs a number of Super Scaffolding commands, so you should never run the test in anything but a clean working copy that can be reset when you're done.
|
28
|
+
|
29
|
+
You can run the setup script and test like so:
|
30
|
+
|
31
|
+
```
|
32
|
+
test/bin/setup-super-scaffolding-system-test
|
33
|
+
rails test test/system/super_scaffolding_test.rb
|
34
|
+
```
|
data/docs/themes.md
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# Themes
|
2
|
+
|
3
|
+
Bullet Train has a theme subsystem designed to allow you the flexibility to either extend or completely replace the stock “Light” and “Clean” UI templates.
|
4
|
+
|
5
|
+
## Inheritance Structure
|
6
|
+
|
7
|
+
To reduce duplication of code across themes, Bullet Train implements an inheritance structure. For example, the official Bullet Train themes are structured hierarchically like so:
|
8
|
+
|
9
|
+
- “Base”
|
10
|
+
- “Bootstrap” (in the future)
|
11
|
+
- “Clean” (in the future)
|
12
|
+
- “Tailwind CSS”
|
13
|
+
- “Light”
|
14
|
+
|
15
|
+
Any component partials that can be shared are pushed up the inheritance structure. For example, [Bullet Train's library of field partials](/docs/field-partials.md) provide a good example of this, illustrating the power of the approach we’ve taken here:
|
16
|
+
|
17
|
+
- The most general field styling varies substantially between Tailwind CSS and Bootstrap, so a `_field.html.erb` component partial exists in both the foundational “Tailwind CSS” and “Bootstrap” themes, but also a further customized version exists in themes like “Light”.
|
18
|
+
- However, many concrete field types like `_text_field.html.erb` and `_phone_field.html.erb` leverage `_field.html.erb`, and they themselves are completely framework agnostic as a result. These partials can live in the shared “Base” theme.
|
19
|
+
|
20
|
+
At run-time, this means:
|
21
|
+
|
22
|
+
- When rendering `_text_field.html.erb`, it renders from “Base”.
|
23
|
+
- However, when `_text_field.html.erb` references `_field.html.erb`, that renders from “Light”.
|
24
|
+
- If you extend “Light” and override `_field.html.erb`, rendering `_text_field.html.erb` will now use your theme’s `_field.html.erb`.
|
25
|
+
|
26
|
+
## Theme Component Usage
|
27
|
+
|
28
|
+
To use a theme component, simply include it from "within" `shared` like so:
|
29
|
+
|
30
|
+
```
|
31
|
+
<%= render 'shared/fields/text_field', method: :text_field_value %>
|
32
|
+
```
|
33
|
+
|
34
|
+
We say "within" because while a `shared` view partial directory does exist, the referenced `shared/fields/_text_field.html.erb` doesn't actually exist within it. Instead, the theme engine picks up on `shared` and also works its way through the theme directories to find the appropriate match.
|
35
|
+
|
36
|
+
### Dealing with Indirection
|
37
|
+
|
38
|
+
This small piece of indirection buys us an incredible amount of power in building and extending themes, but as with any indirection, it could potentially come at the cost of developer experience. That's why Bullet Train includes additional tools for smoothing over this experience. Be sure to read the section on [dealing with indirection].
|
39
|
+
|
40
|
+
|
41
|
+
## Theme Configuration
|
42
|
+
|
43
|
+
You can specify the theme you’d like to use and its inheritance structure in `app/helpers/theme_helper.rb`. The code there is well commented to help you.
|
44
|
+
|
45
|
+
## Theme Structure
|
46
|
+
|
47
|
+
Themes are represented in a few places. Taking “Light” as an example, we have:
|
48
|
+
|
49
|
+
- A directory of theme-specific component partials in `app/views/themes/light`, including a layout ERB template.
|
50
|
+
- A theme-specific stylesheet in `app/javascript/stylesheets/light/application.scss`.
|
51
|
+
- A theme-specific pack in `app/javascript/packs/light.js`. You’ll see there that the actual JavaScript dependencies and code are shared across all themes. The whole purpose of this theme-specific pack is to serve up the theme-specific stylesheet.
|
52
|
+
- Theme-specific logos and images in `app/javascript/images/light`.
|
53
|
+
|
54
|
+
## Adding a New Theme
|
55
|
+
|
56
|
+
To extend the “Light” theme in a new theme called “Tokyo”, we would:
|
57
|
+
|
58
|
+
1. Copy `app/javascript/packs/light.js` to `app/javascript/packs/tokyo.js` and update references to `light` therein to `tokyo`.
|
59
|
+
2. Copy `app/views/themes/light/layouts` to `app/views/themes/tokyo/layouts` and update references to `light` in the contained files to `tokyo`. It's possible this is too much duplication, but in practice most people want to customize these two layouts in their custom themes.
|
60
|
+
3. Create a new file at `app/javascript/stylesheets/tokyo/application.scss`. To start just add `@import "../light/application";` at the top, which represents the fact that “Tokyo” extends “Light”. Any custom styles can be added below that.
|
61
|
+
4. Add `"tokyo"` as the first item in the `THEME_DIRECTORY_ORDER` array in `app/helpers/theme_helper.rb`.
|
62
|
+
|
63
|
+
You should be good to go! We'll try to add a generator for this in the future.
|
64
|
+
|
65
|
+
## Additional Guidance and Principles
|
66
|
+
|
67
|
+
### Should you extend or replace?
|
68
|
+
|
69
|
+
For most development projects, the likely best path for customizing the UI is to extend “Light” or another complete Bullet Train theme. It’s difficult to convey how many hours have gone into making the Bullet Train themes complete and coherent from end to end. Every type of field partial, all the third-party libraries, all the responsiveness scenarios, etc. It’s taken many hours and many invoices.
|
70
|
+
|
71
|
+
Extending an existing theme is like retaining an option on shipping. By extending a theme that is already complete, you allow yourself to say “enough is enough” at a certain point and just living with some inherited defaults in exchange for shipping your product sooner. You can always do more UI work later, but it doesn’t look unpolished now!
|
72
|
+
|
73
|
+
On the other hand, if you decide to try to build a theme from the ground up, you risk getting to that same point, but not being able to stop because there are bits around the edges that don’t feel polished and cohesive.
|
74
|
+
|
75
|
+
### Don’t reference theme component partials directly, even within the same theme!
|
76
|
+
|
77
|
+
#### ❌ Don’t do this, even in theme partials:
|
78
|
+
|
79
|
+
```
|
80
|
+
<%= render "themes/light/box" do |p| %>
|
81
|
+
...
|
82
|
+
<% end %>
|
83
|
+
```
|
84
|
+
|
85
|
+
#### ✅ Instead, always do this:
|
86
|
+
|
87
|
+
```
|
88
|
+
<%= render "shared/box" do |p| %>
|
89
|
+
...
|
90
|
+
<% end %>
|
91
|
+
```
|
92
|
+
|
93
|
+
This allows the theme engine to resolve which theme in the inheritance chain to include the `box` partial from. For example:
|
94
|
+
|
95
|
+
- It might come from the “Light” theme today, but if you switch to the “Bold” theme later, it’ll can start pulling it from there.
|
96
|
+
- If you start extending “Light”, you can override its `box` implementation and your application will pick up the new customized version from your theme automatically.
|
97
|
+
- If (hypothetically) `box` became generalized and move into the parent “Tailwind CSS” theme, your application would pick it up from the appropriate place.
|
98
|
+
|
99
|
+
### Let your designer name their theme.
|
100
|
+
|
101
|
+
You're going to have to call your theme something and there are practical reasons to not call it something generic. If you're pursuing a heavily customized design, consider allowing the designer or designers who are creating the look-and-feel of your application to name their own masterpiece. Giving it a distinct name will really help differentiate things when you're ready to start introducing additional facets to your application or a totally new look-and-feel down the road.
|
data/docs/tunneling.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# HTTP Tunneling with ngrok
|
2
|
+
|
3
|
+
Before your application can take advantage of features that depend on incoming webhooks, you'll need to setup an HTTP tunnel using a service like [ngrok](https://ngrok.com).
|
4
|
+
|
5
|
+
## Use a Paid Plan
|
6
|
+
|
7
|
+
You should specifically sign up for a paid account. Although ngrok offers a free plan, their $5/month paid plan will allow you to reserve a custom subdomain for reuse each time you spin up your tunnel. This is a critical productivity improvement, because in practice you'll end up configuring your tunnel URL in a bunch of different places like `config/application.yml` but also in external systems like when you [configure payment providers to deliver webhooks to you](docs/billing/stripe.md).
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
Once you have ngrok installed, you can start your tunnel like so, replacing `your-subdomain` with whatever subdomain you reserved in your ngrok account:
|
12
|
+
|
13
|
+
```
|
14
|
+
ngrok http 3000 -subdomain=your-subdomain
|
15
|
+
```
|
16
|
+
|
17
|
+
## Updating Your Configuration
|
18
|
+
|
19
|
+
Before your Rails application will accept connections on your tunnel hostname, you need to update `config/application.yml` with:
|
20
|
+
|
21
|
+
```
|
22
|
+
BASE_URL: https://your-subdomain.ngrok.io
|
23
|
+
```
|
24
|
+
|
25
|
+
You'll also need to restart your Rails server:
|
26
|
+
|
27
|
+
```
|
28
|
+
rails restart
|
29
|
+
```
|
data/docs/upgrades.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# Upgrading Your Bullet Train Application
|
2
|
+
|
3
|
+
## Upgrading the Framework
|
4
|
+
|
5
|
+
The vast majority of Bullet Train's functionality is distributed via Ruby gems, so you can pull the latest updates by running `bundle update`.
|
6
|
+
|
7
|
+
## Pulling Updates from the Starter Repository
|
8
|
+
|
9
|
+
There are times when you'll want to pull updates from the starter repository into your local application. Thankfully, `git merge` provides us with the perfect tool for just that. You can simply merge the upstream Bullet Train repository into your local repository. If you haven’t tinkered with the starter repository defaults at all, then this should happen with no meaningful conflicts at all. Simply run your automated tests (including the comprehensive integration tests Bullet Train ships with) to make sure everything is still working as it was before.
|
10
|
+
|
11
|
+
If you _have_ modified some starter repository defaults _and_ we also happened to update that same logic upstream, then pulling the most recent version of the starter repository should cause a merge conflict in Git. This is actually great, because Git will then give you the opportunity to compare our upstream changes with your local customizations and allow you to resolve them in a way that makes sense for your application.
|
12
|
+
|
13
|
+
### 1. Make sure you're working with a clean local copy.
|
14
|
+
|
15
|
+
```
|
16
|
+
git status
|
17
|
+
```
|
18
|
+
|
19
|
+
If you've got uncommitted or untracked files, you can clean them up with the following.
|
20
|
+
|
21
|
+
```
|
22
|
+
# ⚠️ This will destroy any uncommitted or untracked changes and files you have locally.
|
23
|
+
git checkout .
|
24
|
+
git clean -d -f
|
25
|
+
```
|
26
|
+
|
27
|
+
### 2. Fetch the latest and greatest from the Bullet Train repository.
|
28
|
+
|
29
|
+
```
|
30
|
+
git fetch starter-repo
|
31
|
+
````
|
32
|
+
|
33
|
+
### 3. Create a new "upgrade" branch off of your main branch.
|
34
|
+
|
35
|
+
```
|
36
|
+
git checkout main
|
37
|
+
git checkout -b updating-starter-repo
|
38
|
+
```
|
39
|
+
|
40
|
+
### 4. Merge in the newest stuff from Bullet Train and resolve any merge conflicts.
|
41
|
+
|
42
|
+
```
|
43
|
+
git merge starter-repo/main
|
44
|
+
```
|
45
|
+
|
46
|
+
It's quite possible you'll get some merge conflicts at this point. No big deal! Just go through and resolve them like you would if you were integrating code from another developer on your team. We tend to comment our code heavily, but if you have any questions about the code you're trying to understand, let us know on Slack!
|
47
|
+
|
48
|
+
```
|
49
|
+
git diff
|
50
|
+
git add -A
|
51
|
+
git commit -m "Upgrading Bullet Train."
|
52
|
+
```
|
53
|
+
|
54
|
+
### 5. Run Tests.
|
55
|
+
|
56
|
+
```
|
57
|
+
rails test
|
58
|
+
```
|
59
|
+
|
60
|
+
### 6. Merge into `main` and delete the branch.
|
61
|
+
|
62
|
+
```
|
63
|
+
git checkout main
|
64
|
+
git merge updating-starter-repo
|
65
|
+
git push origin main
|
66
|
+
git branch -d updating-starter-repo
|
67
|
+
```
|
68
|
+
|
69
|
+
Alternatively, if you're using GitHub, you can push the `updating-starter-repo` branch up and create a PR from it and let your CI integration do it's thing and then merge in the PR and delete the branch there. (That's what we typically do.)
|
data/lib/bullet_train/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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.39
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Culver
|
@@ -535,6 +535,35 @@ files:
|
|
535
535
|
- db/migrate/20210816072508_add_locale_to_teams.rb
|
536
536
|
- db/migrate/20211020200855_add_doorkeeper_application_to_memberships.rb
|
537
537
|
- db/migrate/20211027002944_add_doorkeeper_application_to_users.rb
|
538
|
+
- docs/api.md
|
539
|
+
- docs/authentication.md
|
540
|
+
- docs/billing/stripe.md
|
541
|
+
- docs/desktop.md
|
542
|
+
- docs/field-partials.md
|
543
|
+
- docs/field-partials/buttons.md
|
544
|
+
- docs/field-partials/super-select.md
|
545
|
+
- docs/font-awesome-pro.md
|
546
|
+
- docs/getting-started.md
|
547
|
+
- docs/heroku.md
|
548
|
+
- docs/i18n.md
|
549
|
+
- docs/index.md
|
550
|
+
- docs/indirection.md
|
551
|
+
- docs/modeling.md
|
552
|
+
- docs/namespacing.md
|
553
|
+
- docs/oauth.md
|
554
|
+
- docs/onboarding.md
|
555
|
+
- docs/overriding.md
|
556
|
+
- docs/permissions.md
|
557
|
+
- docs/seeds.md
|
558
|
+
- docs/super-scaffolding.md
|
559
|
+
- docs/super-scaffolding/delegated-types.md
|
560
|
+
- docs/teams.md
|
561
|
+
- docs/testing.md
|
562
|
+
- docs/themes.md
|
563
|
+
- docs/tunneling.md
|
564
|
+
- docs/upgrades.md
|
565
|
+
- docs/webhooks/incoming.md
|
566
|
+
- docs/webhooks/outgoing.md
|
538
567
|
- lib/bullet_train.rb
|
539
568
|
- lib/bullet_train/engine.rb
|
540
569
|
- lib/bullet_train/resolver.rb
|