Skip to content

Commit caa3edc

Browse files
authored
Merge pull request #72 from basemate/introduce_scaffolder
Introduce scaffolder (documented & tested)
2 parents fa36c6d + 9579f6a commit caa3edc

26 files changed

+497
-9
lines changed

Gemfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,7 @@ group :development, :test do
3232
gem 'byebug'
3333
gem 'webmock'
3434
end
35+
36+
group :test do
37+
gem "generator_spec"
38+
end

Gemfile.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ GEM
9999
docile (1.3.1)
100100
erubi (1.7.1)
101101
ffi (1.9.25)
102+
generator_spec (0.9.4)
103+
activesupport (>= 3.0.0)
104+
railties (>= 3.0.0)
102105
globalid (0.4.2)
103106
activesupport (>= 4.2.0)
104107
haml (5.0.4)
@@ -250,6 +253,7 @@ DEPENDENCIES
250253
capybara
251254
cells-haml
252255
cells-rails
256+
generator_spec
253257
matestack-ui-core!
254258
poltergeist
255259
puma

docs/README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
2. [Concepts](./concepts)
77
3. [Core Components](./components)
88
4. [Integrations](./integrations)
9+
5. [Tooling](./tooling_and_ecosystem)
910

1011
## Diving deeper
1112

12-
5. [Extend](./extend)
13-
6. [Architecture](./architecture)
14-
7. [Contribute](./contribute)
13+
6. [Extend](./extend)
14+
7. [Architecture](./architecture)
15+
8. [Contribute](./contribute)

docs/contribute/README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,9 @@ Tests follow quite the same rules as the documentation: Make sure to either add
2929

3030
## Release
3131

32-
Webpacker is used for managing all JS assets. In order to deploy a packed JS, we
33-
use a "builder" app found in repo_root/builder
34-
This builder app uses a symlink in order to reference the actual core found in
35-
builder/vendor.
32+
Webpacker is used for managing all JS assets. In order to deploy a packed JS, we use a "builder" app found in `repo_root/builder`. This builder app uses a symlink in order to reference the actual core found in `builder/vendor`.
3633

37-
You can run webpacker inside this builder app in order to pack JS assets:
34+
You can run webpacker inside this builder app to pack JS assets:
3835

3936
```shell
4037
cd builder

docs/extend/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# tbd
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Create Matestack concepts using generators
2+
3+
Those are extensions of the `Rails::Generators` and follow the same system as the classic Rails scaffolders. Reach out to us with feedback or if things don't behave the way you'd expect them to do!
4+
5+
## General usage
6+
7+
Create matestack apps, pages and components (and some corresponding parts, like routes and controllers) automatically from the command line!
8+
9+
Each generator takes mandatory arguments and optional flags. Check their detailed description to see default parameters and the full list of options.
10+
11+
Tests can be found [here](../../spec/lib/generators).
12+
13+
**Note:** We recommend commiting or stashing your current changes so you see created/modified files within your application!
14+
15+
Matestack App Generator is documented [here](./matestack_app_generator.md).
16+
17+
Matestack Page Generator is documented [here](./matestack_page_generator.md).
18+
19+
Matestack Component Generator is documented [here](./matestack_component_generator.md).
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Matestack App Generator
2+
3+
## Usage
4+
5+
Generates matestack apps to `app/matestack/apps`.
6+
7+
## Parameters
8+
9+
**NAME** - Mandatory. Creates an empty matestack page in `app/matestack/apps/NAME.rb`.
10+
11+
**--all_inclusive** - Optional. Also creates a corresponding matestack page, a controller with an action for the matestack page and a route to it.
12+
13+
## Example 1
14+
15+
```bash
16+
rails generate matestack_app example_app
17+
```
18+
19+
Creates an ExampleApp in `app/matestack/apps/example_app.rb`.
20+
21+
## Example 2
22+
23+
```bash
24+
rails generate matestack_app simple_app --all_inclusive
25+
```
26+
27+
Creates:
28+
- a SimpleApp in `app/matestack/apps/simple_app.rb`
29+
- an ExamplePage in `app/matestack/pages/simple_app/example_page.rb`
30+
- a SimpleAppController in `app/controllers/simple_app_controller.rb`
31+
- a route to `http://localhost:3000/simple_app/example_page`
32+
33+
To see all options, run
34+
```bash
35+
rails generate matestack_app -h
36+
```
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Matestack Component Generator
2+
3+
## Usage
4+
5+
Generates matestack components to `app/matestack/components`.
6+
7+
## Parameters
8+
9+
**NAME** - Mandatory. Creates an empty matestack component in `app/matestack/components/NAME.rb`.
10+
11+
**--dynamic** - Optional. Makes the created component dynamic and also creates a corresponding `app/matestack/components/NAME.js` file.
12+
13+
**--haml** - Optional. Creates a `app/matestack/components/NAME.haml` file to use 'normal' HTML tags.
14+
15+
**--scss** - Optional. Creates an `app/matestack/components/NAME.scss` for custom component styling.
16+
17+
## Example
18+
19+
```bash
20+
rails generate matestack_component simple_component
21+
```
22+
23+
Creates a SimpleComponent in `app/matestack/components/simple_component.rb`.
24+
25+
To see all options, run
26+
```bash
27+
rails generate matestack_component -h
28+
```
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Matestack Page Generator
2+
3+
## Usage
4+
5+
Generates matestack pages to `app/matestack/pages`.
6+
7+
## Parameters
8+
9+
**NAME** - Mandatory. Creates an empty matestack page in `app/matestack/pages/NAME.rb`.
10+
11+
**--app_name** - Mandatory. Adds a `/app_name` folder to `app/matestack/pages` to indicate to which matestack app the pages belongs. Pages _do not necessarily need to belong to an app_, but for now the page scaffolder can only provide this functionality.
12+
13+
**--namespace** - Optional. Adds a `/namespace` folder within the `/app_name` and a namespace to the `page.rb`. You can also scope the namespace using additional `/`'s like so: `namespace_1/namespace_2`
14+
15+
**--controller_action** - Optional. Takes a `controller#action` to use in the created route for the page. If not provided, a `controller#action` is created from **NAME** and **--app_name**.
16+
17+
## Example 1
18+
19+
```bash
20+
rails generate matestack_page simple_page --app_name example_app
21+
```
22+
23+
Creates a SimplePage in `app/matestack/pages/example_app/simple_page.rb`.
24+
25+
It also adds `get '#example_app/simple_page', to: 'example_app#simple_page'` to the `config/routes.rb` and proposes a
26+
```ruby
27+
def simple_page
28+
responder_for(Pages::ExampleApp::SimplePage)
29+
end
30+
```
31+
in the terminal to use in your controller.
32+
33+
## Example 2
34+
35+
```bash
36+
rails generate matestack_page second_page --app_name example_app --namespace sample_namespace
37+
```
38+
39+
Creates a SimplePage in `app/matestack/pages/example_app/sample_namespace/second_page.rb`.
40+
41+
It also adds `get '#example_app/sample_namespace/second_page', to: 'example_app#second_page'` to the `config/routes.rb` and proposes a
42+
```ruby
43+
def simple_page
44+
responder_for(Pages::ExampleApp::SampleNamespace::SecondPage)
45+
end
46+
```
47+
in the terminal to use in your, e.g., `example_app_controller.rb`.
48+
49+
To see all options, run
50+
```bash
51+
rails generate matestack_page -h
52+
```

lib/generators/matestack_app/USAGE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Description:
2+
Stubs out a new matestack app. Pass the app name under_scored.
3+
4+
If you want so, pass the option '--all_inclusive' to also create
5+
a corresponding matestack example_page, a controller, its action
6+
and the route in 'config/routes.rb'.
7+
8+
Example 1:
9+
`rails generate matestack_app example_app`
10+
11+
This will create:
12+
app/matestack/apps/example_app.rb
13+
14+
Example 2:
15+
`rails generate matestack_app example_app --all_inclusive`
16+
17+
This will create:
18+
app/matestack/apps/example_app.rb
19+
app/matestack/pages/example_app/example_page.rb
20+
app/controllers/example_app_controller.rb
21+
route get 'example_app/example_page', to: 'example_app#example_page'
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class MatestackAppGenerator < Rails::Generators::NamedBase
2+
source_root File.expand_path('templates', __dir__)
3+
4+
class_option :all_inclusive, type: :boolean, default: false
5+
6+
def create_matestack_app
7+
8+
generator_path = "app/matestack/apps/#{file_name}.rb"
9+
10+
template 'matestack_app.erb', generator_path
11+
12+
if options[:all_inclusive] == true
13+
controller_path = "app/controllers/#{file_name}_controller.rb"
14+
template 'matestack_app_controller.erb', controller_path
15+
16+
route %{get '#{file_name}/example_page', to: '#{file_name}\#example_page'}
17+
18+
generate "matestack_page example_page --app_name #{file_name} --called_by_app_generator=true"
19+
20+
puts "You can visit your new matestack apps' example page under http://localhost:3000/#{file_name}/example_page"
21+
22+
end
23+
24+
end
25+
26+
end
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class Apps::<%= class_name %> < Matestack::Ui::App
2+
3+
# OPTIONAL: Prepare data that gets used on every page of this app
4+
# def prepare
5+
# API calls and db queries go here
6+
# end
7+
8+
# MANDATORY: This is where your matestack pages get yielded
9+
def response
10+
components {
11+
page_content
12+
}
13+
end
14+
15+
# OPTIONAL: Use partials to render stuff like layout components
16+
# def partial_one
17+
# partial {
18+
# # your components go here
19+
# }
20+
# end
21+
22+
# OPTIONAL: Slots come after partials
23+
# def slots
24+
# end
25+
26+
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class <%= class_name %>Controller < ApplicationController
2+
3+
def example_page
4+
responder_for(Pages::<%= class_name %>::ExamplePage)
5+
end
6+
7+
end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Description:
2+
Stubs out a new matestack component. Pass the component name, under_scored.
3+
4+
To create a dynamic component, specify it using the --dynamic option.
5+
6+
To place this component within a namespace, specify the namespace name under_scored and it
7+
will get generated into 'app/matestack/components/namespace/*'.
8+
9+
Example 1:
10+
`rails generate matestack_component NAME`
11+
12+
This will create:
13+
app/matestack/components/NAME.rb
14+
15+
Example 2:
16+
`rails generate matestack_component NAME --dynamic --namespace sample_namespace`
17+
18+
This will create:
19+
app/matestack/components/sample_namespace/NAME.rb
20+
app/matestack/components/sample_namespace/NAME.js
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
class MatestackComponentGenerator < Rails::Generators::NamedBase
2+
source_root File.expand_path('templates', __dir__)
3+
4+
class_option :dynamic, type: :boolean, default: false
5+
class_option :scss, type: :boolean, default: false
6+
class_option :haml, type: :boolean, default: false
7+
class_option :namespace, type: :string
8+
9+
def create_matestack_component
10+
@dynamic = options[:dynamic]
11+
@namespace = options[:namespace]
12+
13+
# Future: Check for matestack-compatible namespacing!
14+
15+
to_be_created_files = ['.rb']
16+
to_be_created_files << '.js' if options[:dynamic]
17+
to_be_created_files << '.scss' if options[:scss]
18+
to_be_created_files << '.haml' if options[:haml]
19+
20+
matestack_component_dir_path = "app/matestack/components/"
21+
matestack_component_dir_path << "#{@namespace}/" unless @namespace.nil?
22+
23+
to_be_created_files.each do |file|
24+
generator_path = matestack_component_dir_path + "/#{file_name}#{file}"
25+
template "matestack_component#{file}.erb", generator_path
26+
end
27+
28+
end
29+
30+
end
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.<%= file_name %>{@tag_attributes}
2+
%div
3+
This is your custom <%= class_name %> component
4+
- if block_given?
5+
= yield
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Require your custom component in your application.js before usage
2+
// Place it below "//= require matestack-ui-core" using the following line:
3+
//= require <% unless @namespace.nil? %><%= @namespace %>/<% end %><%= file_name %>
4+
5+
MatestackUiCore.Vue.component('custom<% unless @namespace.nil? %>-<%= @namespace %><% end %>-<%= file_name %>', {
6+
mixins: [MatestackUiCore.componentMixin],
7+
data: function() {
8+
return {
9+
foo: 'bar'
10+
};
11+
},
12+
methods: {},
13+
mounted: function(){
14+
// this is your completeness check and should be deleted before deployment
15+
console.log('Custom Dynamic Component <%= class_name %> mounted!')
16+
}
17+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
class Components::<% unless @namespace.nil? %><%= @namespace.camelize %>::<% end %><%= class_name %> < Matestack::Ui::<% if @dynamic == true %>DynamicComponent<% else %>StaticComponent<% end %>
2+
3+
def prepare
4+
# DB queries and API calls go here
5+
end
6+
7+
def response
8+
components {
9+
# orchestrate existing matestack components here
10+
}
11+
end
12+
13+
end
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// your styles for the component <%= class_name %> go here

0 commit comments

Comments
 (0)