Showing preview only (352K chars total). Download the full file or copy to clipboard to get everything.
Repository: basemate/matestack-ui-core
Branch: main
Commit: aaa4800119a7
Files: 206
Total size: 302.9 KB
Directory structure:
gitextract_mexlutwf/
├── .dockerignore
├── .gitattributes
├── .gitbook.yaml
├── .github/
│ ├── FUNDING.yml
│ ├── issue_template.md
│ ├── pull_request_template.md
│ └── workflows/
│ └── dockerpush.yml
├── .gitignore
├── .rspec
├── .ruby-version
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── Dockerfile.dev
├── Dockerfile.test
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── bin/
│ └── rails
├── ci/
│ ├── Dockerfile.test_5_2_ruby_2_6
│ ├── Dockerfile.test_6_0_ruby_2_6
│ ├── Dockerfile.test_6_1_ruby_2_7
│ ├── Dockerfile.test_6_1_ruby_3_0
│ ├── Dockerfile.test_7_0_ruby_3_0
│ ├── Gemfile.5.2
│ ├── Gemfile.6.0
│ ├── Gemfile.6.1
│ ├── Gemfile.7.0
│ ├── artifacts/
│ │ └── .keep
│ └── docker-compose.ci.yml
├── docker-compose.yml
├── docs/
│ ├── README.md
│ ├── SUMMARY.md
│ ├── components/
│ │ ├── api.md
│ │ ├── registry.md
│ │ ├── usage-in-isolation.md
│ │ ├── usage-on-matestack-layouts.md
│ │ ├── usage-on-matestack-pages.md
│ │ └── usage-on-rails-views.md
│ ├── getting-started/
│ │ ├── hello-world.md
│ │ └── installation-update.md
│ ├── html-rendering/
│ │ ├── html-rendering.md
│ │ ├── integrating-action-view-helpers.md
│ │ └── reusing-views-or-partials.md
│ ├── layouts/
│ │ ├── api.md
│ │ └── rails-controller-integration.md
│ ├── migrate-from-2.x-to-3.0.md
│ └── pages/
│ ├── api.md
│ └── rails-controller-integration.md
├── entrypoint.sh
├── lib/
│ └── matestack/
│ └── ui/
│ ├── component.rb
│ ├── core/
│ │ ├── base.rb
│ │ ├── component.rb
│ │ ├── context.rb
│ │ ├── helper.rb
│ │ ├── layout.rb
│ │ ├── page.rb
│ │ ├── properties.rb
│ │ ├── slots.rb
│ │ ├── tag_helper.rb
│ │ └── version.rb
│ ├── core.rb
│ ├── layout.rb
│ └── page.rb
├── matestack-ui-core.gemspec
├── results.txt
└── spec/
├── core_spec_helper.rb
├── dummy/
│ ├── Rakefile
│ ├── app/
│ │ ├── assets/
│ │ │ ├── config/
│ │ │ │ └── manifest.js
│ │ │ └── images/
│ │ │ └── .keep
│ │ ├── channels/
│ │ │ └── application_cable/
│ │ │ ├── channel.rb
│ │ │ └── connection.rb
│ │ ├── controllers/
│ │ │ ├── application_controller.rb
│ │ │ ├── concerns/
│ │ │ │ └── .keep
│ │ │ ├── demo_core_controller.rb
│ │ │ └── legacy_views/
│ │ │ ├── 0_USED_IN_SPECS_DONT_TOUCH
│ │ │ └── pages_controller.rb
│ │ ├── helpers/
│ │ │ └── application_helper.rb
│ │ ├── javascript/
│ │ │ ├── channels/
│ │ │ │ ├── consumer.js
│ │ │ │ └── index.js
│ │ │ └── packs/
│ │ │ ├── application.js
│ │ │ └── application_core.js
│ │ ├── jobs/
│ │ │ └── application_job.rb
│ │ ├── mailers/
│ │ │ └── application_mailer.rb
│ │ ├── matestack/
│ │ │ ├── components/
│ │ │ │ └── legacy_views/
│ │ │ │ └── pages/
│ │ │ │ ├── 0_USED_IN_SPECS_DONT_TOUCH
│ │ │ │ └── viewcontext.rb
│ │ │ └── demo/
│ │ │ └── core/
│ │ │ ├── components/
│ │ │ │ └── static_component.rb
│ │ │ ├── layout.rb
│ │ │ └── pages/
│ │ │ ├── first_page.rb
│ │ │ └── second_page.rb
│ │ ├── models/
│ │ │ ├── 0_USED_IN_SPECS_DONT_TOUCH
│ │ │ ├── application_record.rb
│ │ │ ├── concerns/
│ │ │ │ └── .keep
│ │ │ ├── dummy_child_model.rb
│ │ │ ├── dummy_model.rb
│ │ │ └── test_model.rb
│ │ └── views/
│ │ ├── _some_partial.html.erb
│ │ ├── demo/
│ │ │ ├── 0_USED_IN_SPECS_DONT_TOUCH
│ │ │ ├── _header.html.erb
│ │ │ └── header.html.erb
│ │ ├── layouts/
│ │ │ ├── 0_USED_IN_SPECS_DONT_TOUCH
│ │ │ ├── application.html.erb
│ │ │ ├── application_core.html.erb
│ │ │ └── legacy_views.erb
│ │ ├── legacy_views/
│ │ │ └── pages/
│ │ │ ├── 0_USED_IN_SPECS_DONT_TOUCH
│ │ │ └── viewcontext_custom_component.html.erb
│ │ ├── rails/
│ │ │ ├── 0_USED_IN_SPECS_DONT_TOUCH
│ │ │ ├── _some_partial.html.erb
│ │ │ └── index.html.erb
│ │ └── some_view.html.erb
│ ├── bin/
│ │ ├── bundle
│ │ ├── rails
│ │ ├── rake
│ │ ├── setup
│ │ ├── update
│ │ ├── webpack
│ │ ├── webpack-dev-server
│ │ └── yarn
│ ├── config/
│ │ ├── application.5.2_rb
│ │ ├── application.6.0_rb
│ │ ├── application.6.1_rb
│ │ ├── application.7.0_rb
│ │ ├── application.rb
│ │ ├── boot.rb
│ │ ├── cable.yml
│ │ ├── database.yml
│ │ ├── environment.rb
│ │ ├── environments/
│ │ │ ├── development.rb
│ │ │ ├── production.rb
│ │ │ └── test.rb
│ │ ├── initializers/
│ │ │ ├── application_controller_renderer.rb
│ │ │ ├── assets.rb
│ │ │ ├── backtrace_silencers.rb
│ │ │ ├── content_security_policy.rb
│ │ │ ├── cookies_serializer.rb
│ │ │ ├── filter_parameter_logging.rb
│ │ │ ├── inflections.rb
│ │ │ ├── matestack.rb
│ │ │ ├── mime_types.rb
│ │ │ ├── nested_attrs_error_index_patch.rb
│ │ │ └── wrap_parameters.rb
│ │ ├── locales/
│ │ │ └── en.yml
│ │ ├── puma.rb
│ │ ├── routes.rb
│ │ ├── spring.rb
│ │ ├── storage.yml
│ │ ├── webpack/
│ │ │ ├── development.js
│ │ │ ├── environment.js
│ │ │ ├── production.js
│ │ │ └── test.js
│ │ └── webpacker.yml
│ ├── config.ru
│ ├── db/
│ │ ├── migrate/
│ │ │ ├── 20190419174203_create_test_models.rb
│ │ │ ├── 20190427134012_create_dummy_models.rb
│ │ │ ├── 20190908153924_create_dummy_child_models.rb
│ │ │ ├── 20200427170812_create_active_storage_tables.active_storage.rb
│ │ │ ├── 20201222161321_add_boolean_value_to_test_models.rb
│ │ │ ├── 20210204135043_add_service_name_to_active_storage_blobs.active_storage.rb
│ │ │ └── 20210204135044_create_active_storage_variant_records.active_storage.rb
│ │ └── schema.rb
│ ├── lib/
│ │ └── assets/
│ │ └── .keep
│ ├── log/
│ │ └── .keep
│ ├── package.json
│ ├── postcss.config.js
│ └── public/
│ ├── 404.html
│ ├── 422.html
│ └── 500.html
├── rails_core_spec_helper.rb
├── spec_helper.rb
└── test/
└── core/
├── base/
│ ├── component/
│ │ ├── argument_spec.rb
│ │ ├── conditional_rendering_spec.rb
│ │ ├── core_namespaces_spec.rb
│ │ ├── custom_namespaces_spec.rb
│ │ ├── options_spec.rb
│ │ ├── partials_spec.rb
│ │ ├── prepare_spec.rb
│ │ ├── properties_spec.rb
│ │ ├── slots_spec.rb
│ │ ├── static_rendering_spec.rb
│ │ ├── url_params_access_spec.rb
│ │ ├── view_context_access_spec.rb
│ │ └── yield_spec.rb
│ ├── layout/
│ │ ├── layout_resolving_spec.rb
│ │ └── layout_spec.rb
│ └── page/
│ ├── controller_instance_access_spec.rb
│ ├── orchestrates_components_spec.rb
│ ├── partials_spec.rb
│ ├── prepare_spec.rb
│ ├── slots_spec.rb
│ ├── url_params_access_spec.rb
│ └── view_context_access_spec.rb
├── custom_component_spec.rb
├── html_rendering/
│ ├── action_view_integration.rb
│ ├── default_tags_spec.rb
│ └── link_spec.rb
├── rails_render_spec.rb
├── support/
│ ├── capybara.rb
│ ├── core_spec_utils.rb
│ ├── example_controller.rb
│ ├── layout.rb
│ ├── matestack_components_controller.rb
│ ├── matestack_wrapper_layout.rb
│ ├── matestack_wrapper_page.rb
│ ├── test_controller.rb
│ └── xss.rb
└── xss_spec.rb
================================================
FILE CONTENTS
================================================
================================================
FILE: .dockerignore
================================================
node_modules/
spec/dummy/db/*.sqlite3
spec/dummy/db/*.sqlite3-journal
spec/dummy/log/*.log
spec/dummy/node_modules/
spec/dummy/public/packs/
spec/dummy/public/packs-test/
spec/dummy/yarn-error.log
spec/dummy/storage/
spec/dummy/tmp/
builder/db/*.sqlite3
builder/db/*.sqlite3-journal
builder/log/*.log
builder/node_modules/
builder/yarn-error.log
builder/storage/
builder/tmp/
builder/public/packs
.idea/
.vscode
.byebug_history
/coverage
================================================
FILE: .gitattributes
================================================
docs/* linguist-documentation
================================================
FILE: .gitbook.yaml
================================================
root: ./docs/
structure:
readme: README.md
summary: SUMMARY.md
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: [matestack]
================================================
FILE: .github/issue_template.md
================================================
<!-- This is a template only, remove/add sections below as appropriate (e.g. for a new feature, there might be no 'current behavior'.) -->
<!-- First indicate whether you want to request an ENHANCEMENT or report a BUG by using the correct Github label in the side panel* -->
**What is the current behavior?**
<!-- add current behavior here -->
**If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug might get fixed faster if we can run your code and it doesn't have extra dependencies. Add a link to a sample repo and/or any relevant code below:**
<!-- add additional links/info here -->
**What is the expected behavior?**
<!-- add expected behavior here -->
**Which versions of Matestack, and which browser/OS are affected by this issue? Did this work in previous versions of Matestack?**
<!-- add version and browser(s) affected, where relevant -->
================================================
FILE: .github/pull_request_template.md
================================================
**Note:** If you submit a feature or bugfix PR, pick **develop** as target branch (and delete this line afterwards).
## Issue https://github.com/matestack/matestack-ui-core/issues/XXX: Short description here
### Changes
- [ ] Describe the changes in one or more bulletpoints
### Notes
- Let the reviewers know something special
================================================
FILE: .github/workflows/dockerpush.yml
================================================
name: specs
on:
push:
paths-ignore:
- 'docs/**'
- 'README.md'
- 'CHANGELOG.md'
jobs:
test_7_0_ruby_3_0:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run tests
run: |
docker-compose -f ./ci/docker-compose.ci.yml run --rm test_7_0_ruby_3_0
- name: Upload lock files
uses: actions/upload-artifact@v2
with:
name: lockfiles_test_7_0_ruby_3_0
path: |
./ci/artifacts/Gemfile.lock
test_6_1_ruby_3_0:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run tests
run: |
docker-compose -f ./ci/docker-compose.ci.yml run --rm test_6_1_ruby_3_0
- name: Upload lock files
uses: actions/upload-artifact@v2
with:
name: lockfiles_test_6_1_ruby_3_0
path: |
./ci/artifacts/Gemfile.lock
test_6_1_ruby_2_7:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run tests
run: |
docker-compose -f ./ci/docker-compose.ci.yml run --rm test_6_1_ruby_2_7
- name: Upload lock files
uses: actions/upload-artifact@v2
with:
name: lockfiles_test_6_1_ruby_2_7
path: |
./ci/artifacts/Gemfile.lock
test_6_0_ruby_2_6:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run tests
run: |
docker-compose -f ./ci/docker-compose.ci.yml run --rm test_6_0_ruby_2_6
- name: Upload lock files
uses: actions/upload-artifact@v2
with:
name: lockfiles_test_6_0_ruby_2_6
path: |
./ci/artifacts/Gemfile.lock
test_5_2_ruby_2_6:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run tests
run: |
docker-compose -f ./ci/docker-compose.ci.yml run --rm test_5_2_ruby_2_6
- name: Upload lock files
uses: actions/upload-artifact@v2
with:
name: lockfiles_test_5_2_ruby_2_6
path: |
./ci/artifacts/Gemfile.lock
================================================
FILE: .gitignore
================================================
.bundle/
log/*.log
node_modules/
coverage/
spec/dummy/db/*.sqlite3
spec/dummy/db/*.sqlite3-journal
spec/dummy/log/*.log
spec/dummy/node_modules/
spec/dummy/public/packs/
spec/dummy/public/packs-test/
spec/dummy/yarn-error.log
spec/dummy/storage/
spec/dummy/tmp/
.idea/
.vscode
.byebug_history
================================================
FILE: .rspec
================================================
--require spec_helper
================================================
FILE: .ruby-version
================================================
2.6.5
================================================
FILE: CHANGELOG.md
================================================
# Changelog
## v3.0.1 Release - 2022-04-29
### Bugfixes
- fixing layout resolving issue when using the `turbo-rails` gem (like seen in a fresh Rails 7 setup)
## v3.0.0 Release - 2022-03-04
- same as v3.0.0.rc2
## v3.0.0.rc2 Release - 2022-02-15
### Bugfixes
- fixing ActionView integration when using Ruby 3.x
## v3.0.0.rc1 Release - 2022-02-11
- Please read the [migration guide](docs/migrate-from-2.x-to-3.0.md)
## v2.1.1 Release - 2021-06-30
### Bugfixes
- Fixed clientside Data Access form new nested forms
## v2.1.0 Release - 2021-06-28
### Improvements
- Nested Form Support #558
- Component render? Method #553
- Page Component Cleanup
- Docs Cleanup
### Bugfixes
- Form Error Reset #539 via #558
- Form File Upload Init File Value #550
## v2.0.0 Release - 2021-04-12
Please refer to the [migration guide](./docs/migrate-from-1.x-to-2.0.md)
## v1.5.0 Release - 2021-03-07
### Improvements
- NPM package usage
## v1.4.0 Release - 2021-02-05
### Improvements
- Ruby 3 support
- Vue update to 2.6.12
- Vuex update to 3.6.2
- Gemspec update clarifying that Rails below 5.2 is not supported (EOL versions anyway!)
- CI test runs against multiple Rails/Ruby version combination
### Bugfixes
- Webpacker 6 support #500
### Security bumps
- Various version bumps triggered through dependabot
## v1.3.2 Release - 2021-01-11
### Bugfixes
- Fixes #503 new vue-turbolinks v2.2.0 causes error on webpacker compile
### Security bumps
- Various version bumps triggered through dependabot
## v1.3.1 Release - 2020-12-28
### Bugfixes
- Fixes #497 Cable component throws browser error when initial content contains form component
## v1.3.0 Release - 2020-12-22
### Potential breaking change
If you have used a `form_submit` component like this:
```ruby
form_submit do
button text: "Submit me!", attributes: { "v-bind:disabled": "loading" }
end
```
in order to disable the the button during submission of the form, please turn `loading` into `loading()`:
```ruby
form_submit do
button text: "Submit me!", attributes: { "v-bind:disabled": "loading()" }
end
```
If you have implemented your own form components, please adjust them as described in the customize section of each form component. Most likely, you now have to provide exactly one root element per form component due to the reworked form components.
### Improvements
- Splitted form API docs into multiple files
- Implements #474 Add HTML `<select>` tag to core components
- Implements #492 Enable extendability of `form_*` components
- Reworked `form_*` components in order to provide a better API for custom form components
- `form_*` components are separate Vue.js components now
- Each `form_*` uses a Vue.js mixin and a Ruby base class. This mixin and base class can be used in custom components in order to easy create own form components
## Bugfixes
- Fixes #490 Custom classes for checkboxes
- Fixes #494 true/false checkboxes are initialized incorrectly
## v1.2.0 Release - 2020-11-20
### Improvements
* Enable usage of Rails view/route helpers on standalone components used via matestack_component helper #476
## v1.1.0 Release - 2020-10-16
### Improvements
* added the `cable` component in order to use ActionCable to update the DOM
## v1.0.1 Release - 2020-10-07
This release contains bugfixes.
### Bugfixes
* Fixed javascript automatic scroll top on page transition for short pages #462
* Enable async components on app level, only usable in pages and components before #458
* Fixed duplicate directory error when using matestack-ui-core with webpacker #460
## v1.0.0 Release - 2020-09-10
Please note that this release contains breaking changes and soft deprecations. To make things easy for users of the current `v0.7.*` version, we have provided **Migration TODOs** at the end of each chapter.
### Migration guide for 0.7.x users
#### 1. Using `render Pages::X` instead of `responder_for(Pages::X)` in controllers
Instead of:
```ruby
class SomeController < ApplicationController
include Matestack::Ui::Core::ApplicationHelper
def some_page
responder_for(Pages::SomePage)
end
end
```
write now:
```ruby
class SomeController < ApplicationController
include Matestack::Ui::Core::ApplicationHelper
def some_page
render Pages::SomePage
end
end
```
Please note that while the `responder_for` method is still being supported, it will be removed in a future release.
**Migration TODOs:**
- [ ] Replace `responder_for` with `render` in your controllers
#### 2. App/Page structure and namespacing
Until `0.7.x`, matestack-ui-core enforced the user to keep apps and pages in a specific folder structure. An app like `Apps::MyApp` had to be stored in `app/matestack/apps/my_app.rb` and an associated page like `Pages::MyApp::MyPage` lived in `app/matestack/pages/my_app/my_page.rb`. The namespace `Pages::MyApp` determined that the page `MyPage` should be wrapped with the layout coming from `Apps::MyApp`.
We changed this behavior in favor of more intuitive namespacing and more control/flexibility on namespaces and folder structure:
**Flexible folder structure and namespacing of apps and pages**
Apps and pages can now actually live anywhere within your project - but we still recommend sticking to some best practices, shown further below. The relation between apps and pages is no longer derived from the (folder) namespace.
**Explicit app/page relation on controller level**
Within a controller, you can now set the desired `matestack_app` that then wraps all pages used in this controller. This definition is inheritable - therefore, you can set in on an `ApplicationController` to make it a default for all controllers and actions, and overwrite it if needed.
Both "global" and "controller-level" `matestack_app` settings can be overwritten on "action-level" using an additional parameter for the `render` method.
The code snippet below shows some common use cases:
```ruby
class SomeController < ApplicationController
include Matestack::Ui::Core::ApplicationHelper
matestack_app MyApp #default for all action on this controller and inherited ones
def some_page
render SomePage
end
def some_page_with_other_app
render SomePage, matestack_app: SomeOtherApp #overwrite controller level matestack_app
end
def some_page_with_other_app
render SomePage, matestack_app: :none #overwrite controller level matestack_app and set to no app at all
end
end
```
**Default App**
If no `matestack_app` is defined or it is deliberately set to `:none` as demonstrated above, matestack-ui-core will by default render the page wrapped by a minimal app. This happens in order to provide basic app-related matestack-ui-core features like `transition` and others.
It is possible to explicitly prevent this behavior by setting `matestack_app` to false:
```ruby
class SomeController < ApplicationController
include Matestack::Ui::Core::ApplicationHelper
def some_page
render SomePage #will render with minimal default app if no app is specified on action or controller level
end
def some_page_with_no_app
render SomePage, matestack_app: false #set to no app at all
end
end
```
**Recommended best practice for app/page folder structure and namespacing**
Imagine your project has two "apps". An "admin" area and a public "website" area. Your folder structure could look like this:
```
app/matestack/
|
└───admin/
│ │ app.rb (`Admin::App < Matestack::Ui::App`)
│ └───pages/
│ │ │ dashboard.rb (`Admin::Pages::Dashboard < Matestack::Ui::Page`)
|
└───website/
│ │ app.rb (`Website::App < Matestack::Ui::App`)
│ └───pages/
│ │ │ home.rb (`Website::Pages::Home < Matestack::Ui::Page`)
```
and your corresponding controllers could look like this:
`app/controllers/admin_controller.rb`
```ruby
class AdminController < ApplicationController
include Matestack::Ui::Core::ApplicationHelper
matestack_app Admin::App
before_action :authenticate_admin! # for example
def dashboard
render Admin::Pages::Dashboard
end
end
```
`app/controllers/website_controller.rb`
```ruby
class WebsiteController < ApplicationController
include Matestack::Ui::Core::ApplicationHelper
matestack_app Website::App
def home
render Website::Pages::Home
end
end
```
**Migration TODOs:**
You can decide to either
- [ ] keep the `0.7.x` folder structure if you want
- [ ] and set the related app on your controllers via `matestack_app` (as it will no longer be derived automatically from the page namespace)
or
- [ ] refactor your app/page structure according to your needs, and set the related apps on a controller level
#### 3. Base component class name adjustments
We decided to rename the base component class names in order to create a better understanding of what they are:
* `Matestack::Ui::StaticComponent` --> `Matestack::Ui::Component`
* `Matestack::Ui::DynamicComponent` --> `Matestack::Ui::VueJsComponent`
**Migration TODOs:**
You can decide to either
- [ ] we still keep the old class names, but we recommend to adjust the base class names as described above
#### 3. Explicit component registration
A major change happened to the component resolving approach. Until `0.7.x`, matestack-ui-core automatically translated core component calls like `some_component` to a class like `Matestack::Ui::Core::Some::Component`, which had to be defined within the core library at `CORE_ROOT/app/concepts/matestack/ui/core/some/component.rb`. The same applied for custom component calls like `custom_my_component` which resolved to a class `Components::My::Component` which had to be defined within the user's application at `APP_ROOT/app/matestack/components/my/component.rb`.
This auto resolving is being completely removed in the `1.0.0` release. All components (core, custom and add-on-engine) have to be registered explicitly as described below:
*Core components*
`CORE_ROOT/lib/matestack/ui/core/components.rb`
```ruby
module Matestack::Ui::Core::Components
#...
require_core_component "some/new/component"
#...
end
Matestack::Ui::Core::Component::Registry.register_components(
#...
some_new_component: Matestack::Ui::Core::Some::New::Component,
#...
)
```
The registered DSL method `some_new_component` does not have to match the components namespace structure.
*Custom components*
Create a registry module like:
`APP_ROOT/app/matestack/components/registry.rb`
```ruby
module Components::Registry
Matestack::Ui::Core::Component::Registry.register_components(
#...
my_component: Components::MyOwnComponent,
#...
)
end
```
and make sure to include this module in your base controller like:
```ruby
class ApplicationController < ActionController::Base
include Matestack::Ui::Core::ApplicationHelper
include Components::Registry
end
```
Like in the core, the registered DSL method `my_component` does not have to match the component's namespace structure. In this example, the custom `MyOwnComponent` lives in `app/matestack/components/my_own_component.rb` and is being referenced as `my_component`.
TBD:
Please be aware that once the component registry was loaded, the initially registered dsl_methods are cached. Removing a dsl_method from the registry will not have an effect until the server gets reloaded. Added dsl_methods however will be available without having to restart the server.
*AddOn engine component*
TODO
**Migration TODOs:**
If you are already using custom components:
- [ ] Add a component registry in `APP_ROOT/app/matestack/components/registry.rb`
- [ ] Register your existing components like ` my_component: Components::MyOwnComponent`, respecting their namespaces and setting dls_methods of your choice. The obligation of prefixing them with a `custom_` does no longer apply.
- [ ] Since the new dls_methods may differ from the former method calls, you need to refactor the custom component usage on existing apps and pages (e.g. formerly `custom_my_own_component` should now be called `my_component`)
#### 4.1 Dynamic (Vue.js) core component naming
Until `1.0.0`, dynamic core components created the Vue.js component name automatically by deriving it from their class name. `Matestack::Ui::Core::Collection::Filter::Filter`, for example, was translated to the Vue.js componente name `matestack-ui-core-collection-filter`. The two occurrences of `Filter` at the end of the class name (which comes from the folder structure and namespacing constraints) was automatically detected and taken care of, so the Vue.js component name only had one occurrence of `filter` in it.
This behavior changes in `1.0.0`:
* `Matestack::Ui::Core::Collection::Filter::Filter` will be translated to `matestack-ui-core-collection-filter-filter` without any further processing per default
* It is now possible to set the Vue.js component name manually within the component configuration:
```ruby
class Matestack::Ui::Core::Collection::Filter::Filter < Matestack::Ui::VueJsComponent
vue_js_component_name "matestack-ui-core-collection-filter"
#...
end
```
**Migration Todos:**
Core developers only:
-[ ] set Vue.js component name explicitly in order to match current Vue.js component names of all dynamic core components
#### 4.2 Dynamic (Vue.js) custom component naming
Formerly, custom components behaved differently than core components. `Components::Some::Component` was translated to a Vue.js component named `custom-some-component`, in order to match their (now changed) dsl method name `custom_some_component`
This behavior changes in `1.0.0`:
* Without any further default processing, `Components::Some::Component` will be translated into `components-some-component`
* It is now possible to set the Vue.js component name manually:
```ruby
class Components::Some::Component < Matestack::Ui::VueJsComponent
vue_js_component_name "some-component"
#...
end
```
**Migration Todos:**
Please note that you have two options, but an action is required to make the new release work with existing custom dynamic components. Either you
- [ ] set Vue.js component name explicitly in order to match current Vue.js component naming of all custom components
OR
- [ ] adapt the name of your custom Vue.js components to the new naming schema demonstrated above
#### 5. No more components block wrapping in Pages/Components/Apps
Instead of:
```ruby
def response
components {
div do
plain "hello!"
end
}
end
```
you can now write:
```ruby
def response
div do
plain "hello!"
end
end
```
Please note that the `components` block is still supported, but will be removed in a `1.0` release.
**Migration Todos:**
- [ ] To be on the safe side, remove all the `components {}` wrapping blocks in your apps and pages
#### 6. Partials are now normal method calls and don't need a block
Instead of writing:
```ruby
def response
components {
div do
partial :my_partial, "foo"
end
}
end
def my_partial param
partial {
plain param
}
end
```
you can now write:
```ruby
def response
div do
my_partial "foo" #normal method call with optional params
end
end
def my_partial param
plain param # no more partial {} block
end
```
Please note that the old `partial` block and method call approach are still supported but will be removed in a `1.0` release.
**Migration Todos:**
- [ ] To be on the safe side, remove all the `partial {}` wrapping blocks in the partials on your apps, pages and custom components
#### 7. Slot syntax stays the same
We still need the `slot` block wrapping around slot content
```ruby
def response
div do
some_static_component my_first_slot: my_simple_slot
end
end
def my_simple_slot
slot do
span id: "my_simple_slot" do
plain "some content"
end
end
end
```
#### 8. `page_content` should now be `yield_page`
We changed the naming to be more expressive and in order to align with the existing `yield_components`
**Migration Todos:**
- [ ] On an app layout, you should now use `yield_page` instead of `page_component`
#### 9. Wrapping DOM structure of pages has changed
We changed the DOM structure around pages in order to enable better page loading state implementations.
We also changed the class names of these wrapping divs in order to better match css naming conventions
```html
<!-- some layout markup -->
<div class="matestack-page-container">
<div class="matestack-page-wrapper">
<div><!--this div is necessary for conditional switch to async template via v-if -->
<div class="matestack-page-root">
your page markup
</div>
</div>
</div>
</div>
<!-- some layout markup -->
```
**Migration Todos:**
- [ ] If you used the old DOM structure and css class names of the wrapping elements for styling, please adjust your CSS accordingly
#### 10. `yield_page` can now take a loading_state slot
In order to simplify the implementation of page loading state effects, we added an optional loading_state slot for `yield_page`:
`app/matestack/example_app/app.rb`
```ruby
class ExampleApp::App < Matestack::Ui::App
def response
# some layout stuff
main do
yield_page slots: { loading_state: my_loading_state_slot }
end
# some layout stuff
end
def my_loading_state_slot
slot do
span class: "some-loading-spinner" do
plain "loading..."
end
end
end
end
```
which will render:
```html
<main>
<div class="matestack-page-container">
<div class="loading-state-element-wrapper">
<span class="some-loading-spinner">
loading...
</span>
</div>
<div class="matestack-page-wrapper">
<div><!--this div is necessary for conditional switch to async template via v-if -->
<div class="matestack-page-root">
your page markup
</div>
</div>
</div>
</div>
</end>
```
and during async page request triggered via transition:
```html
<main>
<div class="matestack-page-container loading">
<div class="loading-state-element-wrapper loading">
<span class="some-loading-spinner">
loading...
</span>
</div>
<div class="matestack-page-wrapper loading">
<div><!--this div is necessary for conditional switch to async template via v-if -->
<div class="matestack-page-root">
your page markup
</div>
</div>
</div>
</div>
</end>
```
You can use the `loading` class and your loading state element to implement CSS based loading state effects.
#### 11. `async` component now requires an ID
We changed the way how matestack resolves the content of an `async` component on rerender calls. It is now required to apply an ID to the `async` component
```ruby
async rerender_on: "some-event", id: "my-unique-id" do
plain hello!
end
```
**Migration Todos:**
- [ ] Please add an unique ID to each `async` component usage, even if matestack is currently auto-generating an ID if not applied. This will be removed in future releases
#### 12. New `toggle` component is replacing `async` shown_on, hide_on, hide_after...
We decided to move all pure clientside view state manipulation logic from the `async` component to a new component called `toggle`. `async` should now only take care of serverside rerendering based on events.
```ruby
async show_on: "some-event" do
plain hello!
end
# should now be:
toggel show_on: "some-event" do
plain hello!
end
```
**Migration Todos:**
- [ ] Please use the new `toggle` component wherever you used `async show_on/hide_on/hide_after`
#### 13. `async` DOM structure and loading state
The `async` components wrapping DOM structure has changed in order to align with the wrapping DOM structure of pages and isolated components:
```ruby
async rerender_on: "some-event", id: "my-unique-id" do
plain hello!
end
```
will render to:
```html
<div class="matestack-async-component-container">
<div class="matestack-async-component-wrapper">
<div id="my-unique-id" class="matestack-async-component-root">
hello!
</div>
</div>
</div>
```
and during rerender:
```html
<div class="matestack-async-component-container loading">
<div class="matestack-async-component-wrapper loading">
<div id="my-unique-id" class="matestack-async-component-root" >
hello!
</div>
</div>
</div>
```
**Migration Todos:**
- [ ] If you used the old DOM structure and css class names of the wrapping elements for styling, please adjust your CSS accordingly
#### 14. `form` component changes
We reworked the form components quite a bit:
- `include` keyword is no longer required
- `form_input` component no longer supports the input type textarea.
- Textareas were extracted in a component and can be used as standalone`textarea` or in forms with `form_textarea`.
- `form_input`component now supports all types according to W3Cs possible types.
- `form_select` is now only used for HTML select dropdowns
- `form_radio` is used for rendering radio button inputs
- `form_checkbox` is used for rendering checkbox inputs, either a single (true/false) checkbox or multiple checkboxes
- options passed as hashes in to `form_select`, `form_radio` and `form_checkbox` are now expected to be { label_value: input_value } and thus the other way around. Until 0.7.6 it was { input_value: label_value }
- and added a lot of new features, such as customizing the error rendering.
We invested a lot of time to improve the `form` API docs found [here](/docs/api/100-components/form.md).
- [ ] Please make sure to read through the docs and migrate your forms accordingly!
#### 15. New approach towards isolated components
We completely rethought the way we approached isolated components.
The old approach:
```ruby
def response
#...
isolate :my_isolated_scope
#...
end
def my_isolated_scope
isolate {
plain "I'm isolated"
}
end
```
is removed.
Instead, we created a new component class `Matestack::Ui::IsolatedComponent`. You can build custom component which inherits from this class in order to create components, which will be resolved completely isolated on rerender calls:
```ruby
class MyPage < Matestack::Ui::Page
def response
#...
my_isolated_component defer: true, public_params: { id: 1 }
#...
end
end
```
```ruby
class MyIsolatedComponent < Matestack::Ui::IsolatedComponent
def prepare
my_model = MyModel.find public_params[:id]
end
def response
div do
plain "#{my_model} was resolved isolated within in a separate http request after page load"
end
end
def authorized?
true
# check access here using current_user for example when using Devise
# true means, this isolated component is public
end
end
```
Using an isolated component with `defer` speeds up the init page load on complex UIs.
**Migration Todos:**
- [ ] Create custom isolated components wherever you used the old approach towards isolate
#### 16. Params access from apps, pages and components
In order to access to request params like we do on controller level, we added the `params` method to apps, pages and components:
```ruby
def response
plain context[:params][:id]
#or
plain @url_params[:id]
end
# should now be:
def response
plain params[:id]
end
```
**Migration Todos:**
- [ ] Switch to the new `params` method in order to access request params. `@url_params` will be deprecated in future releases
#### 16. LICENSE change
As we're performing a major release from 0.7.6 to 1.0.0, we're able to switch the license. We decided to go for the [LGPLv3 license](http://www.gnu.org/licenses/lgpl-3.0.html) following the example of Sidekiq or Trailblazer. That won't have an effect on users of our library as long as you're just using `matestack-ui-core` and not creating/publishing a derivative work. You can use `matestack-ui-core` in commercial closed source applications without any issues.Trailblazer has a comprehensive article on that [topic](https://trailblazer.to/2.1/docs/pro.html#pro-license).
Our goal is to create a sustainable open source project. Therefore we need to secure funding. Selling commercial licenses on top of the LGPLv3 license for companies wanting to create/sell closed source derivative work of `matestack-ui-core` should be one pillar of that funding.
#### 17. Wrap-up
After following all the **Migration Todos**, your application should work just fine. If that's not the case, please [open a GitHub issue](https://github.com/matestack/matestack-ui-core/issues/new) and/or improve this guide!
### Improvements
#### Using matestack components in Rails Views
It is now possible to use `matestack-ui-core` core and custom components in your Rails legacy views. Matestack provides a `matestack_component` helper to use components in views and partials.
Create a custom component like
```ruby
class HeaderComponent < Matestack::Ui::Component
requires :title
def response
header id: 'my-page-header', text: title
end
end
```
and register it in your registry
```ruby
module Components::Registry
Matestack::Ui::Core::Component::Registry.register_components(
header_component: HeaderComponent,
)
end
```
Now, you can go ahead and use it in your views as shown below, even passing arguments works:
```html
<%= matestack_component(:header_component, title: 'A Title') %>
```
### Using Rails Views in Matestack Pages/Components
To render existing rails views inside your components or pages, use the new `rails_view` component. It replaces the old `html` component.
You can render existing partials and views with this helper anywhere in your app. For further information read the `rails_view` documentation.
Let's say you have an old view file in `app/views/example/partial.html.erb`
```html
<p>An example text in a Rails view</p>
```
You could go ahead and re-use it in a component (or simply add it to a page) like:
```ruby
class TextComponent < Matestack::Ui::Component
def response
paragraph text: 'Example text directly in the component'
rails_view path: `example/partial.html.erb`
end
end
```
### Collection select
### Removed Components
#### 1. Inline Component
The Form Inline Component has been removed and can no longer be used.
#### 2. Absolute Component
The Absolute Component has been removed and can no longer be used.
## v0.7.6 - 2020-05-06
[Merged PRs](https://github.com/basemate/matestack-ui-core/pulls?q=is%3Apr+is%3Aclosed+milestone%3A0.7.6)
[Solved Issues](https://github.com/basemate/matestack-ui-core/issues?q=is%3Aissue+is%3Aclosed+milestone%3A0.7.6)
### Security Fixes
* Various dependency version bumps by dependabot
### Bugfixes
* Radio button groups with same values on single page #399
* Async rerendered components have access to ActionView context #405
* Transition component `active` class fixed #408 #410
* Query params were missing in async page load request when using browser history navigation #409
### Improvements
* Apps now have access to ActionView context #405
* Transition component `active-child` class added #410
* Added specs for ActionView context access #411
* Added file upload feature to form (single and multiple) #413
* Added form, transition, action `delay` option #412
* Added form, action `emit` option #412
* Added multi event listening to `async` component option #412 #147
* Added Rails 6 support
* Updated core dev and test environment to Rails 6
* Added form/action `redirect_to` option #415
## v0.7.5 - 2020-03-11
[Merged PRs](https://github.com/basemate/matestack-ui-core/pulls?q=is%3Apr+is%3Aclosed+milestone%3A0.7.5)
[Solved Issues](https://github.com/basemate/matestack-ui-core/issues?q=is%3Aissue+is%3Aclosed+milestone%3A0.7.5)
### Security Fixes
* Various dependency version bumps by dependabot
### Improvements
* Added `datalist` component
* Added `range` type for `form_input`
* Integrated generator specs in CI spec run
* Added `turbolinks` support
* Form component: Add support for `redirect_to` in the controller
* HasViewContext: Check in advance whether the view context would respond to a missing method.
### Bugfixes
* Fixed broken history button behavior introduced in `0.7.4` #386
## v0.7.4 2020-02-10
[Merged PRs](https://github.com/basemate/matestack-ui-core/pulls?q=is%3Apr+is%3Aclosed+milestone%3A0.7.4)
[Solved Issues](https://github.com/basemate/matestack-ui-core/issues?q=is%3Aissue+is%3Aclosed+milestone%3A0.7.4)
### Security Fixes
XSS/Script injection vulnerablilty fixed in 0.7.4
* matestack-ui-core was vulnerable to XSS/Script injection
* matestack-ui-core did not escape strings by default and did not cover this in the docs
* matestack-ui-core should have escaped strings by default in order to prevent XSS/Script injection vulnerability
* 0.7.4 fixes that by performing string escaping by default now
* a new component `unescaped` (like `plain` before) allows to render unescaped strings, but forces the developer to explicitly make a concious decision about that
```ruby
class Pages::MyApp::MyExamplePage < Matestack::Ui::Page
class FakeUser < Struct.new(:name)
end
def prepare
@user = FakeUser.new("<script>alert('such hack many wow')</script>")
end
def response
components {
div do
heading size: 1, text: "Hello #{@user.name}" # was not escaped , from 0.7.4 on it's escaped
plain "Hello #{@user.name}" # was not escaped, from 0.7.4 on it's escaped
unescaped "Hello #{@user.name}" # is not escaped, as intended
end
}
end
end
```
Affected Versions
<= 0.7.3
Patched Versions
>= 0.7.4 --> please update!
Workarounds
escape string explicitly/manually
reported by @PragTob
### Improvements
* On form submit, matestack form values are reset to previous values by fiedl
--> The form component now does not reset itself when using `put`
--> The reset behavior can now be configured (described in `form` component docs)
* Dockerized core dev and test environment by jonasjabari
--> easy local dev and test setup, cross-platform default for dev and testing
--> CI is configured to run tests via dockerized test suite; same as local testing and good base for matrix testing (upcoming)
--> Usage described in contribution docs
* Add `follow_response` option to action component by fiedl
--> same behavior enhancement as added to the `form` component in 0.7.3
--> server may now decide where the transition should navigate to
--> described in `action` component docs
* Add confirm option to action component by fiedl
--> easily add confirmation before performing an action
--> prevent unintended delete action for example
--> described in `action` component docs
* New webpacker features by fiedl
* make webpacker create es5 code instead of es6 code
* Switch to Vue Production Mode if RAILS_ENV=staging or production
* Establish webpack(er) and asset-pipeline workflows
--> webpacker now builds assets for asset pipline usage AND webpacker usage (both usage approaches are described in the installation docs)
--> webpacker now builds minified versions of matestack-ui-core.js (great improvement in file size!)
--> webpacker now builds es5 code, which is compatible with IE11
--> when used via asset pipeline, the minified version of matestack-ui-core together with the production build of vue.js is automatically required
--> when used via webpacker, matestack-ui-core can be used within a modern javascript workflow, importing and extending
single matestack module for example
* New components
* Add HTML `<picture>` tag to core components by pascalwengerter
* Add HTML `<option>` tag to core components by pascalwengerter
* Add HTML `<optgroup>` tag to core components by pascalwengerter
* Add HTML `<iframe>` tag to core components by pascalwengerter
* Add HTML `<dfn>` tag to core components by pascalwengerter
* Add HTML `<del>` tag to core components by pascalwengerter
* Add HTML `<data>` tag to core components by pascalwengerter
* Add HTML `<bdo>` tag to core components by pascalwengerter
* Add HTML `<bdi>` tag to core components by pascalwengerter
* Add HTML `<wbr>` tag to core components by pascalwengerter
* Add HTML `<samp>` tag to core components by pascalwengerter
* Add HTML `<u>` tag to core components by pascalwengerter
* Add HTML `<template>` tag to core components by pascalwengerter
### Bugfixes
* Anchor Link Click triggers full page transition by PragTob
## v0.7.3 - 2019-11-10
[Merged PRs](https://github.com/basemate/matestack-ui-core/pulls?q=is%3Apr+is%3Aclosed+milestone%3A0.7.3)
[Solved Issues](https://github.com/basemate/matestack-ui-core/issues?q=is%3Aissue+is%3Aclosed+milestone%3A0.7.3)
### Potential Breaking Change - Migration Note
Until `0.7.2.1`, we included all `ActionView` modules in `Matestack::Ui::StaticComponent` and `Matestack::Ui::DynamicComponent`. As we didn't use these modules in all of our core components, we decided to move the `ActionView` modules to the new `Matestack::Ui::StaticActionviewComponent` and `Matestack::Ui::DynamicActionviewComponent` class. If you use `ActionView` modules in your components, you have to change the class you inherit from. This might be a potential breaking change for some users - we are not bumping to 0.8.0 as we don't break explicit specified behavior. If you have any problems, reach out via gitter!
### Security Fixes
none
### Improvements
* Move ActionView dependencies to separate, custom-core-component by pascalwengerter
* Add documentation for testing on macOS by marcoroth
* Add HTML `<ruby>` tag to core components by stiwwelll
* Add HTML `<rt>` tag to core components by stiwwelll
* Add HTML `<rp>` tag to core components by stiwwelll
* Add HTML `<q>` tag to core components by GrantBarry
* Add HTML `<pre>` tag to core components by tae8838
* Add HTML `<param>` tag to core components by marcoroth
* Add HTML `<output>` tag to core components by marcoroth
* Add HTML `<object>` tag to core components by pascalwengerter
* Add HTML `<noscript>` tag to core components by stiwwelll
* Add HTML `<meter>` tag to core components by bdlb77
* Add HTML `<mark>` tag to core components by marcoroth
* Add HTML `<map>` tag to core components by pascalwengerter
* Add HTML `<legend>` tag to core components by stiwwelll
* Add HTML `<kbd>` tag to core components by marcoroth
* Add HTML `<ins>` tag to core components by lumisce
* Add HTML `<figure>` tag to core components by lumisce
* Add HTML `<em>` tag to core components by citizen428
* Add HTML `<dt>` tag to core components by mayanktap
* Add HTML `<dl>` tag to core components by mayanktap
* Add HTML `<dd>` tag to core components by mayanktap
* Add HTML `<code>` tag to core components by pascalwengerter
* Add HTML `<cite>` tag to core components by cameronnorman
* Add HTML `<var>` tag to core components by pascalwengerter
* Add HTML `<s>` tag to core components by Manukam
* Add HTML `<bold>` tag to core components by GrantBarry
* Add HTML `<area>` tag to core components by pascalwengerter
* Add tests for video component by MarcoBomfim
* Usage of RecordTagHelper by pascalwengerter
* Add HTML `<aside>` tag to core components by borref
* Add HTML `<address>` tag to core components by michaelrevans
* Add HTML `<sup>` tag to core components by borref
* Add params options to link component documentation by pascalwengerter
### Bugfixes
* Unexpected behavior when creating a record in progress by jonasjabari
* couldn't find file 'matestack_ui_core_manifest.js' on dummy app by jonasjabari
* Add For Attribute to Stand Alone Label Component by bdlb77
* Form component doesn't work on component-level by jonasjabari
* Async component doesn't work on component-level by jonasjabari
## v0.7.2.1 - 2019-09-10
[Merged PRs](https://github.com/basemate/matestack-ui-core/milestone/5?closed=1)
### Security Fixes
- Dependency version bump (nokogiri) by dependabot
### Bugfixes
- Fixed image component 157 #158 by jonasjabari
## v0.7.2 - 2019-09-05
[Merged PRs](https://github.com/basemate/matestack-ui-core/milestone/4?closed=1)
### Security Fixes
- Various dependency version bumps by dependabot
### Improvements
- Add Isolation Component #154 by jonasjabari
- Update integration docs #149 by pascalwengerter
- Add youtube component #144 by pascalwengerter
- Support new Doc App #143 by jonasjabari
- Add class option to dropdown form selects enhancement#135 by 3wille
- Refactor core components v2 enhancement#134 by pascalwengerter
- add sub tag enhancement#132 by pascalwengerter
- Add article component with docs and specs #127 by michaelrevans
- Add address tag, specs and documentation #126 by michaelrevans
- Extra table components #125 by michaelrevans
- Add abbr component with specs and documentation #124 by michaelrevans
- Add article component with docs and specs #122 by michaelrevans
- Add address tag, specs and documentation #121 by michaelrevans
- Add abbr component #120 by michaelrevans
- Add thead, tbody and tfoot components
### Bugfixes
- Add init_show state to async component 140 #152 by jonasjabari
- added missing @tag_attributes #151 by jonasjabari
- update yarn and fix controller action name #141 by pascalwengerter
## v0.7.1 - 2019-08-01
[Merged PRs](https://github.com/basemate/matestack-ui-core/milestone/3?closed=1)
### Improvements
- Introduce scaffolder #72 by PasWen
- Make buttons disableable enhancement by PasWen
- Collection Component #98 by jonasjabari
- Added Async Defer Feature #100 by jonasjabari
- Added blockquote tag to main component #88 by cameronnorman
- Added small tags #87 by cameronnorman
- Added strong tag #93 by cameronnorman
- Added Infos that async component can currently only be used on page leve #85 by jonasjabari was merged 10
- Update span component in 0.7.0 #74 by PasWen
- Add documented, untested video component #70 by PasWen
- Added summary details components #76 by bdlb77
- Add caption with doc and specs enhancement #68 by michaelrevans
### Bugfixes
- Fixed Link Component #84 by jonasjabari
## v0.7.0 - 2019-06-25
### Breaking changes for users
* new base class names for pages, components and apps, issue #36 (@jonasjabari)
* simplified custom component structure/class names #39 (@jonasjabari)
* improved vue.js component naming convention #41 (@jonasjabari)
* `pg` component is now called `paragraph`, issue #47, pull #48 (@PasWen)
### Improvements for users
* added `hr` component, pull #49, (@michaelrevans)
* allow actions to accept id and class attributes, issue #44, pull #50 (@michaelrevans)
### Breaking changes for core developers
* namespaced core components using `Matestack::Ui::Core` module/folder, pull #64 (@jonasjabari)
* simplified core components folder structure, (aligned with issue #39), pull #64 (@jonasjabari)
* changed vue.js component naming, (aligned with issue #41), pull #64 (@jonasjabari)
* add-on engine components now need `Matestack::Ui` namespacing, pull #64 (@jonasjabari)
### Improvements for core developers
* started to move business logic out of `app/concepts` into `app/lib` folder in order to create a better structure (in progress --> core refactoring)
### Migration guide for users from v0.6.0
#### App base class name
***OLD:***
`app/matestack/app/example_app.rb`
```ruby
class Apps::ExampleApp < App::Cell::App end
```
***NEW:***
`app/matestack/app/example_app.rb`
```ruby
class Apps::ExampleApp < Matestack::Ui::App end
```
#### Page base class name
***OLD:***
`app/matestack/pages/example_app/example_page.rb`
```ruby
class Pages::ExampleApp::ExamplePage < Page::Cell::Page end
```
***NEW:***
`app/matestack/pages/example_app/example_page.rb`
```ruby
class Pages::ExampleApp::ExamplePage < Matestack::Ui::Page end
```
#### Custom STATIC component base class name / folder structure
***OLD:***
`app/matestack/components/card/cell/card.rb`
```ruby
class Components::Card::Cell::Card < Component::Cell::Static end
```
***NEW:***
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::StaticComponent end
```
#### Custom DYNAMIC component base class name / folder structure / vue.js naming
***OLD:***
`app/matestack/components/card/cell/card.rb`
```ruby
class Components::Card::Cell::Card < Component::Cell::Dynamic end
```
`app/matestack/components/card/cell/card.js`
```javascript
MatestackUiCore.Vue.component('custom-card-cell', { ... });
```
***NEW:***
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::DynamicComponent end
```
`app/matestack/components/card.js`
```javascript
MatestackUiCore.Vue.component('custom-card', { ... }); //no -cell postfix
```
#### Paragraph component
***OLD:***
`app/matestack/pages/example_app/example_page.rb`
```ruby
class Pages::ExampleApp::ExamplePage < Matestack::Ui::Page
def response
components {
pg do
plain "some text"
end
}
end
end
```
***NEW:***
`app/matestack/pages/example_app/example_page.rb`
```ruby
class Pages::ExampleApp::ExamplePage < Matestack::Ui::Page
def response
components {
paragraph do
plain "some text"
end
}
end
end
```
### Migration guide for core developers from v0.6.0
If you are not a CORE contributor, this part might not be relevant for you ;)
#### Namespaced core components + simplified core components folder/module structure
The core components are moved from `app/concepts` to `app/concepts/matestack/ui/core` in order to stick to the engine namespacing (used in helpers etc...) and therefore scoped like:
```
app/concepts/matestack/ui/core
|
└───div
│ │ div.rb (no cell folder anymore!)
│ │ div.haml (no view folder anymore!)
```
`app/concepts/matestack/ui/core/div/div.rb`
```ruby
module Matestack::Ui::Core::Div
class Div < Matestack::Ui::Core::Component::Static
end
end
```
We also removed the `Cell` module (`cell` folder) and the separate `js` and `view` folders in each component folder in order to simplify folder structure (as we did for custom component development as well)
**Note**
Last module name and class name of CORE components have to be the same. That doesn't apply for CUSTOM components:
`app/matestack/pages/example_app/example_page.rb`
```ruby
class Pages::ExampleApp::ExamplePage < Matestack::Ui::Page
def response
components {
#CORE
div
# looking for 'Matestack::Ui::Core::Div::Div'
# defined in 'app/concepts/matestack/ui/core/div/div.rb'
form_input
# looking for 'Matestack::Ui::Core::Form::Input::Input'
# defined in 'app/concepts/matestack/ui/core/form/input/input.rb'
#CUSTOM
custom_card
# looking for 'Components::Card'
# defined in 'app/matestack/components/card.rb'
custom_fancy_card
# looking for 'Components::Fancy::Card'
# defined in 'app/matestack/components/fancy/card.rb'
}
end
end
```
The reasons why we decided to resolve core components a bit different than custom components are simple:
* we want to make it as easy as possible to create custom components
* we therefore removed the obligatory `Cell` module
* we do not want to force the user to create a subfolder (and therefore module/namespace) in their `components` folder resulting in a class like:
`Components::Card::Card`. It should be as simple as `Components::Card` which is good and intuitive!
* if we would use that simple approach for all our core components, it would lead to a messy code base, as all component cells, views and javascripts live in one big folder.
* we therefore enforce more structure inside the core, using a subfolder for each component within `app/concepts/matestack/ui/core` resulting in a class name for a component like: `Matestack::Ui::Core::Div::Div` (double DIV at the end --> subfolder(module name) :: class)
#### Changed vue.js component naming
Scoping all core components within `Matestack::Ui::Core` is reflected in different vue.js component name as well:
Example: `async` core component
`app/concepts/matestack/ui/core/async`
```javascript
//old
Vue.component('async-cell', componentDef)
//new
Vue.component('matestack-ui-core-async', componentDef)
```
We also removed the `-cell` postfix.
#### Add-on-engine component namespacing
Add-on-engine components now need `Matestack::Ui` namespacing:
Example:
```
ADDON_ENGINE_ROOT/app/concepts/matestack/ui/materialize
|
└───row
│ │ row.rb
│ │ row.haml
```
`ADDON_ENGINE_ROOT/app/concepts/matestack/ui/materialize/row/row.rb`
```ruby
module Matestack::Ui::Materialize::Row
class Row < Matestack::Ui::Core::Component::Static
def response
components {
div class: "row" do
yield_components
end
}
end
end
end
```
Usage:
`app/matestack/pages/example_app/example_page.rb`
```ruby
class Pages::ExampleApp::ExamplePage < Matestack::Ui::Page
def response
components {
#CORE
div
# looking for 'Matestack::Ui::Core::Div::Div'
# defined in 'CORE_ENGINE_ROOT/app/concepts/matestack/ui/core/div/div.rb'
#ENGINE
materialize_row
# looking for 'Matestack::Ui::Materialize::Row::Row'
# defined in 'ADDON_ENGINE_ROOT/app/concepts/matestack/ui/materialize/row/row.rb'
}
end
end
```
## v0.6.0 - 2019-04-27
### Improvements
* added documentation
* added tests
## v0.6.0.pre.1 - 2019-02-26
This release is marked as PRE. Test coverage is not sufficient at the moment.
### Breaking Changes
* Form component now need the ':include' keyword in order to populate the form config to its children
* Input components are now renamed to form_* in order to show their dependency to a parent form component
### Improvements
* partials may now be defined in modules and used across multiple page classes
* components may now define required attributes, which get validated automatically
* components now raises more specific error messages
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at pascal@matestack.io. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
================================================
FILE: Dockerfile.dev
================================================
FROM ruby:3.0-alpine3.12
RUN gem install bundler:2.1.4
RUN apk update --no-cache && \
apk add build-base postgresql-dev git nodejs yarn tzdata bash sqlite-dev npm libtool && \
mkdir -p /app
WORKDIR /app
COPY ./lib/ /app/lib/
COPY matestack-ui-core.gemspec /app/
COPY Gemfile* /app/
RUN bundle install
================================================
FILE: Dockerfile.test
================================================
FROM ruby:3.0-alpine3.12
RUN gem install bundler:2.1.4
RUN apk update --no-cache && \
apk add build-base postgresql-dev git nodejs yarn tzdata bash sqlite-dev npm libtool && \
mkdir -p /app
WORKDIR /app
COPY ./lib/ /app/lib/
COPY matestack-ui-core.gemspec /app/
COPY Gemfile* /app/
RUN bundle install
RUN apk update && apk upgrade \
&& echo @edge http://nl.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories \
&& echo @edge http://nl.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories \
&& apk add --no-cache \
chromium=86.0.4240.111-r0 \
nss@edge \
&& rm -rf /var/lib/apt/lists/* \
/var/cache/apk/* \
/usr/share/man \
/tmp/*
RUN apk add chromium-chromedriver=86.0.4240.111-r0
ENV CHROME_BIN=/usr/bin/chromium-browser \
CHROME_PATH=/usr/lib/chromium/
================================================
FILE: Gemfile
================================================
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
# Declare your gem's dependencies in matestack-ui-core.gemspec.
# Bundler will treat runtime dependencies like base dependencies, and
# development dependencies will be added by default to the :development group.
gemspec
# Declare any dependencies that are still in development here instead of in
# your gemspec. These might include edge Rails or gems from your path or
# Git. Remember to move these dependencies to your gemspec before releasing
# your gem to rubygems.org.
gem 'rails', '~> 7.0.1'
gem 'turbo-rails'
group :development, :test do
gem 'rspec-rails', '~> 4.0.2'
gem 'capybara'
gem 'webpacker', '~> 5.0'
gem 'pg', '>= 0.18', '< 2.0'
gem 'selenium-webdriver'
gem 'puma'
gem 'simplecov', require: false, group: :test
gem 'byebug'
gem 'webmock'
end
group :test do
gem 'pry-rails'
gem 'pry-byebug'
gem "generator_spec"
# gem "rspec-retry" # repeating flaky tests
# gem "rspec-wait", "~> 0.0.9"
end
================================================
FILE: LICENSE
================================================
Copyright (c) MateLab GmbH
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
[](https://github.com/matestack/matestack-ui-core/actions)
[](https://discord.com/invite/c6tQxFG)
[](https://badge.fury.io/rb/matestack-ui-core)
[](https://docs.matestack.io)
[](https://twitter.com/matestack)

# matestack-ui-core | Component based web UIs in pure Ruby for Rails
Boost your productivity & easily create component based web UIs in pure Ruby.
`matestack-ui-core` enables you to craft maintainable web UIs in pure Ruby, skipping ERB and HTML. UI code becomes a native and fun part of your Rails app. `matestack-ui-core` can progressively replace the classic Rails-View-Layer. You are able to use
it alongside your classic views.
## Compatibility
`matestack-ui-core` is tested against:
- Rails 7.0.1 + Ruby 3.0.0
- Rails 6.1.1 + Ruby 3.0.0
- Rails 6.1.1 + Ruby 2.7.2
- Rails 6.0.3.4 + Ruby 2.6.6
- Rails 5.2.4.4 + Ruby 2.6.6
Rails versions below 5.2 are not supported.
## Documentation/Installation
Documentation can be found [here](https://docs.matestack.io/matestack-ui-core)
## Getting started
A getting started guide can be found [here](https://docs.matestack.io/matestack-ui-core/getting-started/hello-world)
## Changelog
Changelog can be found [here](./CHANGELOG.md)
## Community
As a low-barrier feedback channel for our early users, we have set up a Discord server that can be found [here](https://discord.com/invite/c6tQxFG). You are very welcome to ask questions and send us feedback there!
## Contribution
We are happy to accept contributors of any kind! In order to make it as easy and fun as possible to contribute to `matestack-ui-core`, we would like to onboard contributors personally! Best way to become a contributor: Ping us on Discord! We will schedule a video call with you and show you, how and what to work on :)
## Feature walk-through
### 1. Create UI components in pure Ruby
Craft your UI based on your components written in pure Ruby. Utilizing Ruby's amazing language features, you're able to create a cleaner and more maintainable UI implementation.
#### Implement UI components in pure Ruby
Create Ruby classes within your Rails project and call matestack's core components through a Ruby DSL in order to craft your UIs.
The Ruby method \"div\" for example calls one of the static core components, responsible for rendering HTML tags. A component can take Strings, Integers Symbols, Arrays or Hashes (...) as optional properties (e.g. \"title\") or require them (e.g. \"body\").
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::Component
required :body
optional :title
optional :image
def response
div class: "card shadow-sm border-0 bg-light" do
img path: context.image, class: "w-100" if context.image.present?
div class: "card-body" do
h5 context.title if context.title.present?
paragraph context.body, class: "card-text"
end
end
end
end
```
#### Use your Ruby UI components on your existing Rails views
Components can be then called on Rails views (not only! see below), enabling you to create a reusable card components, abstracting UI complexity in your own components.
`app/views/your_view.html.erb`
```erb
<!-- some other erb markup -->
<%= Components::Card.call(title: "hello", body: "world") %>
<!-- some other erb markup -->
```
#### Use Ruby methods as partials
Split your UI implementation into multiple small chunks helping others (and yourself) to better understand your implementation.
Using this approach helps you to create a clean, readable and maintainable codebase.
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::Component
required :body
optional :title
optional :image
optional :footer
def response
div class: "card shadow-sm border-0 bg-light" do
img path: context.image, class: "w-100" if context.image.present?
card_content
card_footer if context.footer.present?
end
end
def card_content
div class: "card-body" do
h5 context.title if context.title.present?
paragraph context.body, class: "card-body"
end
end
def card_footer
div class: "card-footer text-muted" do
plain context.footer
end
end
end
```
`app/views/your_view.html.erb`
```erb
<!-- some other erb markup -->
<%= Components::Card.call(title: "hello", body: "world", footer: "foo") %>
<!-- some other erb markup -->
```
#### Use class inheritance
Because it's just a Ruby class, you can use class inheritance in order to further improve the quality of your UI implementation.
Class inheritance can be used to easily create variants of UI components but still reuse parts of the implementation.
`app/matestack/components/blue_card.rb`
```ruby
class Components::BlueCard < Components::Card
def response
div class: "card shadow-sm border-0 bg-primary text-white" do
img path: context.image, class: "w-100" if context.image.present?
card_content #defined in parent class
card_footer if context.footer.present? #defined in parent class
end
end
end
```
`app/views/your_view.html.erb`
```erb
<!-- some other erb markup -->
<%= Components::BlueCard.call(title: "hello", body: "world") %>
<!-- some other erb markup -->
```
#### Use components within components
Just like you used matestack's core components on your own UI component, you can use your own UI components within other custom UI components.
You decide when using a Ruby method partial should be replaced by another self contained UI component!
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::Component
required :body
optional :title
optional :image
def response
div class: "card shadow-sm border-0 bg-light" do
img path: context.image, class: "w-100" if context.image.present?
# calling the CardBody component rather than using Ruby method partials
Components::CardBody.call(title: context.title, body: context.body)
end
end
end
```
`app/matestack/components/card_body.rb`
```ruby
class Components::CardBody < Matestack::Ui::Component
required :body
optional :title
def response
# Just an example. Would make more sense, if this component had
# a more complex structure
div class: "card-body" do
h5 context.title if context.title.present?
paragraph context.body, class: "card-body"
end
end
end
```
#### Yield components into components
Sometimes it's not enough to just pass simple data into a component. No worries! You can just yield a block into your components!
Using this approach gives you more flexibility when using your UI components. Ofcourse yielding can be used alongside passing in simple params.
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::Component
required :body
optional :title
optional :image
def response
div class: "card shadow-sm border-0 bg-light" do
img path: context.image, class: "w-100" if context.image.present?
Components::CardBody.call() do
# yielding a block into the card_body component
h5 context.title if context.title.present?
paragraph context.body, class: "card-body"
end
end
end
end
```
`app/matestack/components/card_body.rb`
```ruby
class Components::CardBody < Matestack::Ui::Component
def response
# Just an example. Would make more sense, if this component had
# a more complex structure
div class: "card-body" do
yield if block_given?
end
end
end
```
#### Use named slots for advanced content injection
If you need to inject multiple blocks into your UI component, you can use \"slots\"!
Slots help you to build complex UI components with multiple named content placeholders for highest implementation flexibility!
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::Component
required :body
optional :title
optional :image
def response
div class: "card shadow-sm border-0 bg-light" do
img path: context.image, class: "w-100" if context.image.present?
Components::CardBody.call(slots: {
heading: method(:heading_slot),
body: method(:body_slot)
})
end
end
def heading_slot
h5 context.title if context.title.present?
end
def body_slot
paragraph context.body, class: "card-body"
end
end
```
`app/matestack/components/card_body.rb`
```ruby
class Components::CardBody < Matestack::Ui::Component
required :slots
def response
# Just an example. Would make more sense, if this component had
# a more complex structure
div class: "card-body" do
div class: "heading-section" do
slot :heading
end
div class: "body-section" do
slot :body
end
end
end
end
```
## License
`matestack-ui-core` is an Open Source project licensed under the terms of the [MIT license](./LICENSE)
================================================
FILE: Rakefile
================================================
begin
require 'bundler/setup'
rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end
require 'rdoc/task'
RDoc::Task.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'Matestack::Ui::Core'
rdoc.options << '--line-numbers'
rdoc.rdoc_files.include('README.md')
rdoc.rdoc_files.include('lib/**/*.rb')
end
APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
load 'rails/tasks/engine.rake'
load 'rails/tasks/statistics.rake'
require 'bundler/gem_tasks'
require 'rake/testtask'
# Rake::TestTask.new(:test) do |t|
# t.libs << 'test'
# t.pattern = 'test/**/*_test.rb'
# t.verbose = false
# end
#
# task default: :test
task :webpack => 'webpack:build'
namespace :webpack do
task :build => ['build:development', 'build:production']
namespace :build do
task :development => 'yarn:install' do
Bundler.with_unbundled_env do
sh "cd builder && bin/webpack"
end
end
task :production => 'yarn:install' do
Bundler.with_unbundled_env do
sh "cd builder && bin/rake webpacker:compile"
end
end
end
task :watch => 'yarn:install' do
Bundler.with_unbundled_env do
sh "cd builder && bin/webpack --watch"
end
end
namespace :yarn do
task :install do
sh "yarn install && cd builder && yarn install"
end
end
end
================================================
FILE: bin/rails
================================================
#!/usr/bin/env ruby
# This command will automatically be run when you run "rails" with Rails gems
# installed from the root of your application.
# ENGINE_ROOT = File.expand_path('..', __dir__)
# ENGINE_PATH = File.expand_path('../lib/matestack/ui/core/engine', __dir__)
APP_PATH = File.expand_path('../spec/dummy/config/application', __dir__)
# Set up gems listed in the Gemfile.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
require 'rails/all'
require 'rails/engine/commands'
================================================
FILE: ci/Dockerfile.test_5_2_ruby_2_6
================================================
FROM ruby:2.6-alpine3.12
RUN gem install bundler:2.1.4
RUN apk update --no-cache && \
apk add build-base postgresql-dev git nodejs yarn tzdata bash sqlite-dev shared-mime-info npm && \
mkdir -p /app
WORKDIR /app
COPY ./lib/ /app/lib/
COPY matestack-ui-core.gemspec /app/
COPY ./ci/Gemfile.5.2 /app/Gemfile
RUN bundle install
RUN apk update && apk upgrade \
&& echo @edge http://nl.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories \
&& echo @edge http://nl.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories \
&& apk add --no-cache \
chromium=86.0.4240.111-r0 \
nss@edge \
&& rm -rf /var/lib/apt/lists/* \
/var/cache/apk/* \
/usr/share/man \
/tmp/*
RUN apk add chromium-chromedriver=86.0.4240.111-r0
ENV CHROME_BIN=/usr/bin/chromium-browser \
CHROME_PATH=/usr/lib/chromium/
RUN mv Gemfile _Gemfile
RUN mv Gemfile.lock _Gemfile.lock
COPY . /app
RUN rm Gemfile
RUN rm Gemfile.lock
RUN mv _Gemfile Gemfile
RUN mv _Gemfile.lock Gemfile.lock
WORKDIR /app/spec/dummy
RUN npm install
RUN ./bin/webpack
RUN rm ./db/schema.rb
RUN rm ./config/application.rb
RUN mv ./config/application.5.2_rb /app/spec/dummy/config/application.rb
WORKDIR /app
================================================
FILE: ci/Dockerfile.test_6_0_ruby_2_6
================================================
FROM ruby:2.6-alpine3.12
RUN gem install bundler:2.1.4
RUN apk update --no-cache && \
apk add build-base postgresql-dev git nodejs yarn tzdata bash sqlite-dev shared-mime-info npm && \
mkdir -p /app
WORKDIR /app
COPY ./lib/ /app/lib/
COPY matestack-ui-core.gemspec /app/
COPY ./ci/Gemfile.6.0 /app/Gemfile
RUN bundle install
RUN apk update && apk upgrade \
&& echo @edge http://nl.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories \
&& echo @edge http://nl.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories \
&& apk add --no-cache \
chromium=86.0.4240.111-r0 \
nss@edge \
&& rm -rf /var/lib/apt/lists/* \
/var/cache/apk/* \
/usr/share/man \
/tmp/*
RUN apk add chromium-chromedriver=86.0.4240.111-r0
ENV CHROME_BIN=/usr/bin/chromium-browser \
CHROME_PATH=/usr/lib/chromium/
RUN mv Gemfile _Gemfile
RUN mv Gemfile.lock _Gemfile.lock
COPY . /app
RUN rm Gemfile
RUN rm Gemfile.lock
RUN mv _Gemfile Gemfile
RUN mv _Gemfile.lock Gemfile.lock
WORKDIR /app/spec/dummy
RUN npm install
RUN ./bin/webpack
RUN rm ./db/schema.rb
RUN rm ./config/application.rb
RUN mv ./config/application.6.0_rb /app/spec/dummy/config/application.rb
WORKDIR /app
================================================
FILE: ci/Dockerfile.test_6_1_ruby_2_7
================================================
FROM ruby:2.7-alpine3.12
RUN gem install bundler:2.1.4
RUN apk update --no-cache && \
apk add build-base postgresql-dev git nodejs yarn tzdata bash sqlite-dev shared-mime-info npm && \
mkdir -p /app
WORKDIR /app
COPY ./lib/ /app/lib/
COPY matestack-ui-core.gemspec /app/
COPY ./ci/Gemfile.6.1 /app/Gemfile
RUN bundle install
RUN apk update && apk upgrade \
&& echo @edge http://nl.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories \
&& echo @edge http://nl.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories \
&& apk add --no-cache \
chromium=86.0.4240.111-r0 \
nss@edge \
&& rm -rf /var/lib/apt/lists/* \
/var/cache/apk/* \
/usr/share/man \
/tmp/*
RUN apk add chromium-chromedriver=86.0.4240.111-r0
ENV CHROME_BIN=/usr/bin/chromium-browser \
CHROME_PATH=/usr/lib/chromium/
RUN mv Gemfile _Gemfile
RUN mv Gemfile.lock _Gemfile.lock
COPY . /app
RUN rm Gemfile
RUN rm Gemfile.lock
RUN mv _Gemfile Gemfile
RUN mv _Gemfile.lock Gemfile.lock
WORKDIR /app/spec/dummy
RUN npm install
RUN ./bin/webpack
RUN rm ./db/schema.rb
RUN rm ./config/application.rb
RUN mv ./config/application.6.1_rb /app/spec/dummy/config/application.rb
WORKDIR /app
================================================
FILE: ci/Dockerfile.test_6_1_ruby_3_0
================================================
FROM ruby:3.0-alpine3.12
RUN gem install bundler:2.1.4
RUN apk update --no-cache && \
apk add build-base postgresql-dev git nodejs yarn tzdata bash sqlite-dev shared-mime-info npm && \
mkdir -p /app
WORKDIR /app
COPY ./lib/ /app/lib/
COPY matestack-ui-core.gemspec /app/
COPY ./ci/Gemfile.6.1 /app/Gemfile
RUN bundle install
RUN apk update && apk upgrade \
&& echo @edge http://nl.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories \
&& echo @edge http://nl.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories \
&& apk add --no-cache \
chromium=86.0.4240.111-r0 \
nss@edge \
&& rm -rf /var/lib/apt/lists/* \
/var/cache/apk/* \
/usr/share/man \
/tmp/*
RUN apk add chromium-chromedriver=86.0.4240.111-r0
ENV CHROME_BIN=/usr/bin/chromium-browser \
CHROME_PATH=/usr/lib/chromium/
RUN mv Gemfile _Gemfile
RUN mv Gemfile.lock _Gemfile.lock
COPY . /app
RUN rm Gemfile
RUN rm Gemfile.lock
RUN mv _Gemfile Gemfile
RUN mv _Gemfile.lock Gemfile.lock
WORKDIR /app/spec/dummy
RUN npm install
RUN ./bin/webpack
RUN rm ./db/schema.rb
RUN rm ./config/application.rb
RUN mv ./config/application.6.1_rb /app/spec/dummy/config/application.rb
WORKDIR /app
================================================
FILE: ci/Dockerfile.test_7_0_ruby_3_0
================================================
FROM ruby:3.0-alpine3.12
RUN gem install bundler:2.1.4
RUN apk update --no-cache && \
apk add build-base postgresql-dev git nodejs yarn tzdata bash sqlite-dev shared-mime-info npm && \
mkdir -p /app
WORKDIR /app
COPY ./lib/ /app/lib/
COPY matestack-ui-core.gemspec /app/
COPY ./ci/Gemfile.7.0 /app/Gemfile
RUN bundle install
RUN apk update && apk upgrade \
&& echo @edge http://nl.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories \
&& echo @edge http://nl.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories \
&& apk add --no-cache \
chromium=86.0.4240.111-r0 \
nss@edge \
&& rm -rf /var/lib/apt/lists/* \
/var/cache/apk/* \
/usr/share/man \
/tmp/*
RUN apk add chromium-chromedriver=86.0.4240.111-r0
ENV CHROME_BIN=/usr/bin/chromium-browser \
CHROME_PATH=/usr/lib/chromium/
RUN mv Gemfile _Gemfile
RUN mv Gemfile.lock _Gemfile.lock
COPY . /app
RUN rm Gemfile
RUN rm Gemfile.lock
RUN mv _Gemfile Gemfile
RUN mv _Gemfile.lock Gemfile.lock
WORKDIR /app/spec/dummy
RUN npm install
RUN ./bin/webpack
RUN rm ./db/schema.rb
RUN rm ./config/application.rb
RUN mv ./config/application.7.0_rb /app/spec/dummy/config/application.rb
WORKDIR /app
================================================
FILE: ci/Gemfile.5.2
================================================
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
# Declare your gem's dependencies in matestack-ui-core.gemspec.
# Bundler will treat runtime dependencies like base dependencies, and
# development dependencies will be added by default to the :development group.
gemspec
# Declare any dependencies that are still in development here instead of in
# your gemspec. These might include edge Rails or gems from your path or
# Git. Remember to move these dependencies to your gemspec before releasing
# your gem to rubygems.org.
gem 'rails', '5.2.4.4'
group :development, :test do
gem 'rspec-rails', '~> 3.8'
gem 'capybara'
gem 'webpacker', '~> 4.0'
gem 'pg', '>= 0.18', '< 2.0'
gem 'selenium-webdriver'
gem 'puma'
gem 'simplecov', require: false, group: :test
gem 'byebug'
gem 'webmock'
gem 'turbolinks'
end
group :test do
gem 'pry-rails'
gem 'pry-byebug'
gem "generator_spec"
gem "rspec-retry" # repeating flaky tests
gem "rspec-wait", "~> 0.0.9"
end
================================================
FILE: ci/Gemfile.6.0
================================================
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
# Declare your gem's dependencies in matestack-ui-core.gemspec.
# Bundler will treat runtime dependencies like base dependencies, and
# development dependencies will be added by default to the :development group.
gemspec
# Declare any dependencies that are still in development here instead of in
# your gemspec. These might include edge Rails or gems from your path or
# Git. Remember to move these dependencies to your gemspec before releasing
# your gem to rubygems.org.
gem 'rails', '6.0.3.4'
group :development, :test do
gem 'rspec-rails', '~> 3.8'
gem 'capybara'
gem 'webpacker', '~> 4.0'
gem 'pg', '>= 0.18', '< 2.0'
gem 'selenium-webdriver'
gem 'puma'
gem 'simplecov', require: false, group: :test
gem 'byebug'
gem 'webmock'
gem 'turbolinks'
end
group :test do
gem 'pry-rails'
gem 'pry-byebug'
gem "generator_spec"
gem "rspec-retry" # repeating flaky tests
gem "rspec-wait", "~> 0.0.9"
end
================================================
FILE: ci/Gemfile.6.1
================================================
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
# Declare your gem's dependencies in matestack-ui-core.gemspec.
# Bundler will treat runtime dependencies like base dependencies, and
# development dependencies will be added by default to the :development group.
gemspec
# Declare any dependencies that are still in development here instead of in
# your gemspec. These might include edge Rails or gems from your path or
# Git. Remember to move these dependencies to your gemspec before releasing
# your gem to rubygems.org.
gem 'rails', '6.1.1'
group :development, :test do
gem 'rspec-rails', '~> 4.0.2'
gem 'capybara'
gem 'webpacker', '~> 4.0'
gem 'pg', '>= 0.18', '< 2.0'
gem 'selenium-webdriver'
gem 'puma'
gem 'simplecov', require: false, group: :test
gem 'byebug'
gem 'webmock'
gem 'turbolinks'
end
group :test do
gem 'pry-rails'
gem 'pry-byebug'
gem "generator_spec"
gem "rspec-retry" # repeating flaky tests
gem "rspec-wait", "~> 0.0.9"
end
================================================
FILE: ci/Gemfile.7.0
================================================
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
# Declare your gem's dependencies in matestack-ui-core.gemspec.
# Bundler will treat runtime dependencies like base dependencies, and
# development dependencies will be added by default to the :development group.
gemspec
# Declare any dependencies that are still in development here instead of in
# your gemspec. These might include edge Rails or gems from your path or
# Git. Remember to move these dependencies to your gemspec before releasing
# your gem to rubygems.org.
gem 'rails', '7.0.1'
group :development, :test do
gem 'rspec-rails', '~> 4.0.2'
gem 'capybara'
gem 'webpacker', '~> 4.0'
gem 'pg', '>= 0.18', '< 2.0'
gem 'selenium-webdriver'
gem 'puma'
gem 'simplecov', require: false, group: :test
gem 'byebug'
gem 'webmock'
gem 'turbolinks'
end
group :test do
gem 'pry-rails'
gem 'pry-byebug'
gem "generator_spec"
gem "rspec-retry" # repeating flaky tests
gem "rspec-wait", "~> 0.0.9"
end
================================================
FILE: ci/artifacts/.keep
================================================
================================================
FILE: ci/docker-compose.ci.yml
================================================
version: '3'
services:
test_5_2_ruby_2_6:
build:
context: ../
dockerfile: ./ci/Dockerfile.test_5_2_ruby_2_6
environment:
RAILS_ENV: test
volumes:
- "../ci/artifacts:/app/ci/artifacts"
links:
- "postgres_test_5_2_ruby_2_6:postgres_test"
command: sh -c "bundle exec rake db:drop && bundle exec rake db:create && bundle exec rake db:migrate && bundle exec rspec spec/test/core && cp Gemfile.lock ./ci/artifacts/Gemfile.lock"
user: ${CURRENT_UID}
test_6_0_ruby_2_6:
build:
context: ../
dockerfile: ./ci/Dockerfile.test_6_0_ruby_2_6
environment:
RAILS_ENV: test
volumes:
- "../ci/artifacts:/app/ci/artifacts"
links:
- "postgres_test_6_0_ruby_2_6:postgres_test"
command: sh -c "bundle exec rake db:drop && bundle exec rake db:create && bundle exec rake db:migrate && bundle exec rspec spec/test/core && cp Gemfile.lock ./ci/artifacts/Gemfile.lock"
user: ${CURRENT_UID}
test_6_1_ruby_2_7:
build:
context: ../
dockerfile: ./ci/Dockerfile.test_6_1_ruby_2_7
environment:
RAILS_ENV: test
volumes:
- "../ci/artifacts:/app/ci/artifacts"
links:
- "postgres_test_6_1_ruby_2_7:postgres_test"
command: sh -c "bundle exec rake db:drop && bundle exec rake db:create && bundle exec rake db:migrate && bundle exec rspec spec/test/core && cp Gemfile.lock ./ci/artifacts/Gemfile.lock"
user: ${CURRENT_UID}
test_6_1_ruby_3_0:
build:
context: ../
dockerfile: ./ci/Dockerfile.test_6_1_ruby_3_0
environment:
RAILS_ENV: test
volumes:
- "../ci/artifacts:/app/ci/artifacts"
links:
- "postgres_test_6_1_ruby_3_0:postgres_test"
command: sh -c "bundle exec rake db:drop && bundle exec rake db:create && bundle exec rake db:migrate && bundle exec rspec spec/test/core && cp Gemfile.lock ./ci/artifacts/Gemfile.lock"
user: ${CURRENT_UID}
test_7_0_ruby_3_0:
build:
context: ../
dockerfile: ./ci/Dockerfile.test_7_0_ruby_3_0
environment:
RAILS_ENV: test
volumes:
- "../ci/artifacts:/app/ci/artifacts"
links:
- "postgres_test_7_0_ruby_3_0:postgres_test"
command: sh -c "bundle exec rake db:drop && bundle exec rake db:create && bundle exec rake db:migrate && bundle exec rspec spec/test/core && cp Gemfile.lock ./ci/artifacts/Gemfile.lock"
user: ${CURRENT_UID}
postgres_test_base: &postgres_test_base
image: postgres
expose:
- 5432
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: test
postgres_test_7_0_ruby_3_0:
<<: *postgres_test_base
postgres_test_6_1_ruby_3_0:
<<: *postgres_test_base
postgres_test_6_1_ruby_2_7:
<<: *postgres_test_base
postgres_test_6_0_ruby_2_6:
<<: *postgres_test_base
postgres_test_5_2_ruby_2_6:
<<: *postgres_test_base
================================================
FILE: docker-compose.yml
================================================
version: '3'
services:
dummy:
build:
context: .
dockerfile: ./Dockerfile.dev
ports:
- "3000:3000"
environment:
RAILS_ENV: development
links:
- postgres_dummy
volumes:
- ./:/app
- gem-volume:/usr/local/bundle
command: "bundle exec rails server -b 0.0.0.0"
user: ${CURRENT_UID}
stdin_open: true
tty: true
webpack-watcher:
build:
context: .
dockerfile: ./Dockerfile.dev
environment:
RAILS_ENV: development
volumes:
- ./:/app
- gem-volume:/usr/local/bundle
command: "sh -c 'cd spec/dummy && ./bin/webpack --watch'"
user: ${CURRENT_UID}
test:
build:
context: .
dockerfile: ./Dockerfile.test
environment:
RAILS_ENV: test
links:
- postgres_test
ports:
- "33123:33123"
volumes:
- ./:/app
- gem-volume:/usr/local/bundle
command: "bundle exec rspec spec/test"
user: ${CURRENT_UID}
postgres_dummy:
image: postgres
expose:
- 5432
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: dummy
volumes:
- dummy-data-volume:/var/lib/postgresql/data
postgres_test_base: &postgres_test_base
image: postgres
expose:
- 5432
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: test
postgres_test:
<<: *postgres_test_base
volumes:
test-data-volume:
dummy-data-volume:
gem-volume:
================================================
FILE: docs/README.md
================================================
---
description: >-
Matestack Ui Core - Boost your productivity & easily create component based
web UIs in pure Ruby.
---
# Welcome
{% hint style="info" %}
Version 3.0.0 was released on the xth of February 2022. Click here for more [details](migrate-from-2.x-to-3.0.md)
**Most important changes:**
* Split `matestack-ui-core` into `matestack-ui-core` and `matestack-ui-vuejs`
* Rails 7 support
* Vue 3 support in `matestack-ui-vuejs`
****
**If you want to see the docs for Version 2.1, click** [**here**](https://docs.matestack.io/matestack-ui-core/v/2.1/)**:**
{% endhint %}
## **About**
`matestack-ui-core` enables you to craft maintainable, **component based** web UIs in **pure Ruby**, skipping ERB and HTML. UI code becomes a native and fun part of your Rails app. It can progressively replace the classic Rails-View-Layer. You are able to use it alongside your Rails views.
## Compatibility
`matestack-ui-core` is automatically tested against:
* Rails 7.0.1 + Ruby 3.0.0
* Rails 6.1.1 + Ruby 3.0.0
* Rails 6.1.1 + Ruby 2.7.2
* Rails 6.0.3.4 + Ruby 2.6.6
* Rails 5.2.4.4 + Ruby 2.6.6
{% hint style="danger" %}
Rails versions below 5.2 are not officially supported.
{% endhint %}
## Getting Started
Start right away and install `matestack-ui-core` on top of your Rails app, or read something about the features below.
{% content-ref url="getting-started/installation-update.md" %}
[installation-update.md](getting-started/installation-update.md)
{% endcontent-ref %}
## Feature walk-through
### 1. Create UI components in pure Ruby
Craft your UI based on your components written in pure Ruby. Utilizing Ruby's amazing language features, you're able to create a cleaner and more maintainable UI implementation.
**Implement UI components in pure Ruby**
Create Ruby classes within your Rails project and call Matestack's core components through a Ruby DSL in order to craft your UIs. The Ruby method "div" for example calls one of the static core components, responsible for rendering HTML tags. A component can take Strings, Integers Symbols, Arrays or Hashes (...) as optional properties (e.g. "title") or require them (e.g. "body").
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::Component
required :body
optional :title
optional :image
def response
div class: "card shadow-sm border-0 bg-light" do
img path: context.image, class: "w-100" if context.image.present?
div class: "card-body" do
h5 context.title if context.title.present?
paragraph context.body, class: "card-text"
end
end
end
end
```
**Use your Ruby UI components on your existing Rails views**
Components can be then called on Rails views (not only! see below), enabling you to create a reusable card components, abstracting UI complexity in your own components.
`app/views/your_view.html.erb`
```erb
<!-- some other erb markup -->
<%= Components::Card.call(title: "hello", body: "world") %>
<!-- some other erb markup -->
```
**Use Ruby methods as partials**
Split your UI implementation into multiple small chunks helping others (and yourself) to better understand your implementation. Using this approach helps you to create a clean, readable and maintainable codebase.
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::Component
required :body
optional :title
optional :image
optional :footer
def response
div class: "card shadow-sm border-0 bg-light" do
img path: context.image, class: "w-100" if context.image.present?
card_content
card_footer if context.footer.present?
end
end
def card_content
div class: "card-body" do
h5 context.title if context.title.present?
paragraph context.body, class: "card-body"
end
end
def card_footer
div class: "card-footer text-muted" do
plain footer
end
end
end
```
`app/views/your_view.html.erb`
```erb
<!-- some other erb markup -->
<%= Components::Card.call(title: "hello", body: "world", footer: "foo") %>
<!-- some other erb markup -->
```
**Use class inheritance**
Because it's just a Ruby class, you can use class inheritance in order to further improve the quality of your UI implementation. Class inheritance can be used to easily create variants of UI components but still reuse parts of the implementation.
`app/matestack/components/blue_card.rb`
```ruby
class Components::BlueCard < Components::Card
def response
div class: "card shadow-sm border-0 bg-primary text-white" do
img path: context.image, class: "w-100" if context.image.present?
card_content #defined in parent class
card_footer if context.footer.present? #defined in parent class
end
end
end
```
`app/views/your_view.html.erb`
```erb
<!-- some other erb markup -->
<%= Components::BlueCard.call(title: "hello", body: "world") %>
<!-- some other erb markup -->
```
**Use components within components**
Just like you used matestack's core components on your own UI component, you can use your own UI components within other custom UI components. You decide when using a Ruby method partial should be replaced by another self contained UI component!
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::Component
required :body
optional :title
optional :image
def response
div class: "card shadow-sm border-0 bg-light" do
img path: context.image, class: "w-100" if context.image.present?
# calling the CardBody component rather than using Ruby method partials
Components::CardBody.call(title: context.title, body: context.body)
end
end
end
```
`app/matestack/components/card_body.rb`
```ruby
class Components::CardBody < Matestack::Ui::Component
required :body
optional :title
def response
# Just an example. Would make more sense, if this component had
# a more complex structure
div class: "card-body" do
h5 context.title if context.title.present?
paragraph context.body, class: "card-body"
end
end
end
```
**Yield components into components**
Sometimes it's not enough to just pass simple data into a component. No worries! You can just yield a block into your components! Using this approach gives you more flexibility when using your UI components. Ofcourse yielding can be used alongside passing in simple params.
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::Component
required :body
optional :title
optional :image
def response
div class: "card shadow-sm border-0 bg-light" do
img path: context.image, class: "w-100" if context.image.present?
Components::CardBody.call() do
# yielding a block into the card_body component
h5 context.title if context.title.present?
paragraph context.body, class: "card-body"
end
end
end
end
```
`app/matestack/components/card_body.rb`
```ruby
class Components::CardBody < Matestack::Ui::Component
def response
# Just an example. Would make more sense, if this component had
# a more complex structure
div class: "card-body" do
yield if block_given?
end
end
end
```
**Use named slots for advanced content injection**
If you need to inject multiple blocks into your UI component, you can use "slots"! Slots help you to build complex UI components with multiple named content placeholders for highest implementation flexibility!
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::Component
required :body
optional :title
optional :image
def response
div class: "card shadow-sm border-0 bg-light" do
img path: context.image, class: "w-100" if context.image.present?
Components::CardBody.call(slots: {
heading: method(:heading_slot),
body: method(:body_slot)
})
end
end
def heading_slot
h5 context.title if context.title.present?
end
def body_slot
paragraph context.body, class: "card-body"
end
end
```
`app/matestack/components/card_body.rb`
```ruby
class Components::CardBody < Matestack::Ui::Component
required :slots
def response
# Just an example. Would make more sense, if this component had
# a more complex structure
div class: "card-body" do
div class: "heading-section" do
slot :heading
end
div class: "body-section" do
slot :body
end
end
end
end
```
### 2. Substitute Rails Views with Matestack Pages
Until here we used Matestack components on Rails views. If desired you can go one step further and use Matestack components on something called a Matestack Page:
A Matestack page can be compared to a Rails view and might be yielded within a layout provided by an associated Matestack layout class (see below). The page itself uses Matestack's HTML rendering mechanism in a `response` method and may additionally call other components in order to define a specific UI.
{% code title="app/matestack/pages/some_page.rb" %}
```ruby
class Pages::SomePage < Matestack::Ui::Page
def response
div class: "container" do
span id: "hello" do
plain "hello world!"
end
Components::Card.call(title: "foo", body: "bar")
end
end
end
```
{% endcode %}
Pages are used as Rails view substitutes and therefore called in a Rails controller action:
{% code title="app/controllers/some_controller.rb" %}
```ruby
class SomeController < ApplicationController
include Matestack::Ui::Core::Helper
def overview
render Pages::SomePage
end
end
```
{% endcode %}
The page response - in this case - will be yielded into the Rails layout if not specified differently.
### 3. Wrap Matestack Pages in Matestack Layouts
Just like a Rails layout would yield a Rails view, a Matestack layout yields a Matestack page. The layout uses Matestack's HTML rendering mechanism in a `response` method and may additionally call other components in order to define a specific UI.
{% code title="app/matestack/some_app/some_layout.rb" %}
```ruby
class SomeApp::SomeLayout < Matestack::Ui::Layout
def response
h1 "Some App"
main do
yield
end
end
end
```
{% endcode %}
In this basic example the layout is using the methods `h1` and `main` in order to create the markup as well as a `yield` in order to yield a page on a specific position.
{% hint style="info" %}
A Matestack layout itself will be yielded into the Rails layout, unless the Rails layout is disabled in the controller via:`layout false`
{% endhint %}
Usually a layout implies a specific context of your application. Multiple pages are then scoped within that context, which could lead to a file structure like:
```bash
app/matestack/
|
└───some_app/
│ │ some_layout.rb
│ └───pages/
│ │ │ page1.rb
│ │ │ page2.rb
│ │ │ page3.rb
```
and then used in a controller like this:
{% code title="app/controllers/some_controller.rb" %}
```ruby
class SomeController < ApplicationController
include Matestack::Ui::Core::Helper
matestack_layout SomeApp::SomeLayout
def page_1
render SomeApp::Pages::Page1
end
def page_2
render SomeApp::Pages::Page2
end
def page_3
render SomeApp::Pages::Page3, matestack_layout: false # skip app layout on this page
end
end
```
{% endcode %}
================================================
FILE: docs/SUMMARY.md
================================================
# Table of contents
* [Welcome](README.md)
* [Migrating from 2.x to 3.0](migrate-from-2.x-to-3.0.md)
## Getting started
* [Installation & Update](getting-started/installation-update.md)
* [Hello World](getting-started/hello-world.md)
## HTML Rendering
* [Basic Rendering Mechanism](html-rendering/html-rendering.md)
* [Integrating Action View Helpers](html-rendering/integrating-action-view-helpers.md)
* [Integrating Rails Views or Partials](html-rendering/reusing-views-or-partials.md)
## Components
* [API](components/api.md)
* [Usage on Rails Views](components/usage-on-rails-views.md)
* [Usage on Matestack Pages](components/usage-on-matestack-pages.md)
* [Usage on Matestack Layouts](components/usage-on-matestack-layouts.md)
* [Usage in Isolation](components/usage-in-isolation.md)
* [Registry](components/registry.md)
## Pages
* [API](pages/api.md)
* [Rails Controller Integration](pages/rails-controller-integration.md)
## Layouts
* [API](layouts/api.md)
* [Rails Controller Integration](layouts/rails-controller-integration.md)
================================================
FILE: docs/components/api.md
================================================
# API
## Response
Use the `response` method to define the UI of the component by using Matestack's HTML rendering or calling components.
```ruby
class SomeComponent < Matestack::Ui::Component
def response
div id: "my-component" do
plain "hello world!"
end
SomeOtherComponent.()
end
end
```
```ruby
class ExamplePage < Matestack::Ui::Page
def response
div id: "div-on-page" do
SomeComponent.()
end
end
end
```
## Partials and helper methods
Use partials to keep the code dry and indentation layers manageable!
### Local partials on component level
In the component definition, see how this time from inside the response, the `my_partial` method below is called:
```ruby
class SomeComponent < Matestack::Ui::Component
def response
div id: "my-component" do
my_partial "foo from component"
end
end
private # optionally mark your partials as private
def my_partial text
div class: "nested"
plain text
end
end
end
```
### Partials defined in modules
Extract code snippets to modules for an even better project structure. First, create a module:
```ruby
module MySharedPartials
def my_partial text
div class: "nested"
plain text
end
end
end
```
Include the module in the component:
```ruby
class SomeComponent < Matestack::Ui::Component
include MySharedPartials
def response
div id: "my-component" do
my_partial "foo from component"
end
end
end
```
### Helper methods
Not only can instance methods be used as "partials" but as general helpers performing any kind of logic or data resolving:
```ruby
class SomeComponent < Matestack::Ui::Component
def response
div id: "my-component" do
if is_admin?
latest_users.each do |user|
div do
plain user.name # ...
end
end
else
plain "not authorized"
end
end
end
private # optionally mark your helper methods as private
def is_admin?
true # some crazy Ruby logic!
end
def latest_users
User.last(10) # calling ActiveRecord models for example
end
end
```
## Render?
Use the `render?` method to conditionally render the component based on custom rules:
```ruby
class AdminComponent < Matestack::Ui::Component
required :user
def render?
context.user.admin?
end
def response
div id: "admin-component" do
plain "This component should only get rendered for admins"
end
end
end
```
This is particularly useful to avoid plastering your views with conditional statements like `if` and `unless`.
Instead of:
```ruby
<% if current_user.admin? %>
<%= Components::AdminComponent.(user: current_user) %>
<% end %>
```
You can just use:
```ruby
<%= Components::AdminComponent.(user: current_user) %>
```
## Prepare
Use a prepare method to resolve instance variables before rendering a component if required.
```ruby
class SomeComponent < Matestack::Ui::Component
def prepare
@some_data = "some data"
end
def response
div id: "my-component" do
plain @some_data
end
end
end
```
```ruby
class ExamplePage < Matestack::Ui::Page
def response
div id: "div-on-page" do
SomeComponent.()
end
end
end
```
This is the HTML which gets created:
```markup
<div id="div-on-page">
<div id="my-component">
some data
</div>
</div>
```
## Params access
A component can access request information, e.g. url query params, by calling the `params` method:
```ruby
class SomeComponent < Matestack::Ui::Component
def response
div id: "my-component" do
plain params[:foo]
end
end
end
```
On the example page, reference the component as usual.
```ruby
class ExamplePage < Matestack::Ui::Page
def response
div id: "div-on-page" do
SomeComponent.()
end
end
end
```
Now, visiting the respective route to the page, e.g. via `/xyz?foo=bar`, the component reads the `[:foo]` from the params and displays it like so:
```markup
<div id="div-on-page">
<div id="my-component">
bar
</div>
</div>
```
## Passing data to components
You often need to pass data into your component to make them reusable. You have multiple possibilities to do that:
### General options access
If you pass in a hash to a component...
```ruby
class ExamplePage < Matestack::Ui::Page
def response
div id: "div-on-page" do
SomeComponent.(foo: "bar")
end
end
end
```
...this hash is accessible via options in the component:
```ruby
class Some::Component < Matestack::Ui::Component
def response
div id: "my-component" do
plain options[:foo]
end
end
end
```
### Optional and required options
Matestack components give you the possibility to define an explicit API for your component describing required and optional options for a component. Using this approach, it's way easier to understand what data can be processed by your component.
{% hint style="info" %}
`required` and `optional` options will be deleted from the `options` hash and are only available via the `context` object.
{% endhint %}
#### Required options
Required options are required for your component to work, like the name suggests. If at least one required option is missing, an Exception is raised.
Declare your required options by calling `required` as follows:
```ruby
class SomeComponent < Matestack::Ui::Component
required :some_property, :some_other
end
```
You then can use these options simply by calling the provided OpenStruct object `context`, which includes the injected options with their name:
```ruby
class SomeComponent < Matestack::Ui::Component
required :some_property, :some_other
def response
# display some_property plain inside a div and some_other property inside a paragraph beneath it
div do
plain context.some_property
end
paragraph text: context.some_other
end
end
```
#### Optional options
To define optional options you can use the same syntax as `required`. Just use `optional` instead of `required`. Optional options are optional and not validated for presence like required options.
```ruby
class SomeComponent < Matestack::Ui::Component
optional :optional_property, :other_optional_property # optional properties could be empty
def response
div do
plain context.optional_property
end
paragraph context.other_optional_property
end
end
```
#### Passing more complex data structures to components
You can pass any object you like and use it in the component with the helper.
```ruby
class SomeComponent < Matestack::Ui::Component
required :some_option,
optional :some_other
def response
div do
plain context.some_option
end
if context.some_other.present?
paragraph context.some_other[:option]
end
end
end
```
Use it in the example page and pass in one option as a hash
```ruby
class ExamplePage < Matestack::Ui::Page
def prepare
@hello = "hello!"
end
def response
div id: "div-on-page" do
SomeComponent.(some_option: @hello, some_other: { option: "world!" })
end
end
end
```
#### Alias properties
It's not possible to overwrite core methods of the OpenStruct object `context`
```markup
[:!, :!=, :!~, :<=>, :==, :===, :=~, :[], :[]=, :__id__, :__send__, :acts_like?, :as_json, :blank?, :byebug, :class, :class_eval, :clone, :dclone, :debugger, :deep_dup, :define_singleton_method, :delete_field, :dig, :display, :dup, :duplicable?, :each_pair, :enum_for, :eql?, :equal?, :extend, :freeze, :frozen?, :gem, :hash, :html_safe?, :in?, :inspect, :instance_eval, :instance_exec, :instance_of?, :instance_values, :instance_variable_defined?, :instance_variable_get, :instance_variable_names, :instance_variable_set, :instance_variables, :is_a?, :itself, :kind_of?, :load_dependency, :marshal_dump, :marshal_load, :method, :method_missing, :methods, :nil?, :object_id, :presence, :presence_in, :present?, :pretty_inspect, :pretty_print, :pretty_print_cycle, :pretty_print_inspect, :pretty_print_instance_variables, :private_methods, :protected_methods, :public_method, :public_methods, :public_send, :remote_byebug, :remove_instance_variable, :require_dependency, :require_or_load, :respond_to?, :send, :singleton_class, :singleton_method, :singleton_methods, :table, :table!, :taint, :tainted?, :tap, :then, :to_enum, :to_h, :to_json, :to_param, :to_query, :to_s, :to_yaml, :trust, :try, :try!, :unloadable, :untaint, :untrust, :untrusted?, :with_options, :yield_self]
```
If you somehow want to inject options with a key matching a core method of the OpenStruct object, simply provide an alias name with the `as:` option. You can then use the alias accordingly. A popular example would be the option called `class`
```ruby
class SomeComponent < Matestack::Ui::Component
required :foo, :bar, class: { as: :my_class }
def response
div class: context.my_class do
plain "#{context.foo} - #{context.bar}"
end
end
end
```
### Text argument
Sometimes you just want to pass in a simple (text) argument rather than a hash with multiple keys:
```ruby
class ExamplePage < Matestack::Ui::Page
def response
div id: "div-on-page" do
# simply pass in a string here
SomeComponent.("foo from page")
end
end
end
```
A component can access this text argument in various ways:
```ruby
class Some::Component < Matestack::Ui::Component
def response
div id: "my-component" do
plain self.text # because such an argument is almost always a string
# or
plain context.text # for compatibility with older releases
end
end
end
```
This approach can be combined with injecting Hashes to components:
```ruby
class ExamplePage < Matestack::Ui::Page
def response
div id: "div-on-page" do
# simply pass in a string here
Some::Component.("foo from page", { foo: "bar" })
end
end
end
```
```ruby
class Some::Component < Matestack::Ui::Component
optional :foo
def response
div id: "my-component" do
plain self.text # because such an argument is almost always a string
# or
plain context.text # for compatibility with older releases
plain context.foo
end
end
end
```
## Yielding inside components
Components can yield a block with access to scope, where a block is defined.
```ruby
class SomeComponent < Matestack::Ui::Component
def response
div id: "my-component" do
yield
end
end
end
```
Pass a block to a component on the page as shown below:
```ruby
class ExamplePage < Matestack::Ui::Page
def prepare
@foo = "foo from page"
end
def response
div id: "div-on-page" do
SomeComponent.() do
plain @foo
end
end
end
end
```
Not a fancy example, but this is the result:
```markup
<div id="div-on-page">
<div id="my-component">
foo from page
</div>
</div>
```
## Slots
Slots in Matestack allow us to inject whole UI snippets into the component. It's a more specific yielding mechanism as you will yield multiple "named blocks" into the component. Each of these blocks can be referenced and positioned independently in the component,
### Slots on the page instance scope
Define the slots within the component file as shown below. Please make sure to inject slots within a hash `slots: { ... }` into the component.
```ruby
class SomeComponent < Matestack::Ui::Component
def prepare
@foo = "foo from component"
end
def response
div id: "my-component" do
slot :my_first_slot
br
slot :my_second_slot
end
end
end
```
Slots have access to the scope of the class, where they are defined. In this case `@foo`
```ruby
class ExamplePage < Matestack::Ui::Page
def prepare
@foo = "foo from page"
end
def response
div do
some_component slots: {
my_first_slot: method(:my_simple_slot),
my_second_slot: method(:my_second_simple_slot)
}
end
end
def my_simple_slot
span id: "my_simple_slot" do
plain "some content"
end
end
def my_second_simple_slot
span id: "my_simple_slot" do
plain @foo
end
end
end
```
This gets rendered into HTML as shown below. Notice that the `@foo` from the component configuration got overwritten by the page's local `@foo`!
```markup
<div>
<div id="my-component">
<span id="my_simple_slot">
some content
</span>
<br/>
<span id="my_simple_slot">
foo from page
</span>
</div>
</div>
```
### Using slots of components within components
To use _component instance scope slots_, first define slots within a static component:
```ruby
class Other::Component < Matestack::Ui::Component
def prepare
@foo = "foo from other component"
end
def response
div id: "my-other-component" do
slot :my_slot_from_component
br
slot :my_slot_from_page
br
plain @foo
end
end
end
```
and also in some component:
```ruby
class Some::Component < Matestack::Ui::Component
def prepare
@foo = "foo from component"
end
def response
div id: "my-component" do
other_component slots: {
my_slot_from_component: method(:my_slot_from_component),
my_slot_from_page: slots[:my_slot_from_page]
}
end
end
def my_slot_from_component
span id: "my-slot-from-component" do
plain @foo
end
end
end
```
Then, put both components (note that some component uses other component so that's how they're both in here) to use on the example page:
```ruby
class ExamplePage < Matestack::Ui::Page
def prepare
@foo = "foo from page"
end
def response
div id: "page-div" do
some_component slots: { my_slot_from_page: method(:my_slot_from_page) }
end
end
def my_slot_from_page
span id: "my-slot-from-page" do
plain @foo
end
end
end
```
This gets rendered into the HTML below:
```markup
<div id="page-div">
<div id="my-component">
<div id="my-other-component">
<span id="my-slot-from-component">
foo from component
</span>
<br/>
<span id="my-slot-from-page">
foo from page
</span>
<br/>
foo from other component
</div>
</div>
</div>
```
### Calling slots with params
Sometimes it's necessary to call a slot with params:
```ruby
class SomeComponent < Matestack::Ui::Component
def response
div id: "my-component" do
User.last(10).each do |user|
slot(:user_card, user)
end
end
end
end
```
```ruby
class ExamplePage < Matestack::Ui::Page
def response
div do
some_component slots: {
user_card: method(:user_card)
}
end
end
def user_card user
div class: "card" do
plain user.name
end
end
end
```
================================================
FILE: docs/components/registry.md
================================================
# Registry
By default, components can be called directly like `Components::Card.call(title: "foo", body: "bar")` which will return the desired HTML string.
If desired, you can create alias methods in order to avoid the class call syntax:
{% code title="app/matestack/components/registry.rb" %}
```ruby
module Components::Registry
def card(text=nil, options=nil, &block)
Components::Card.call(text, options, &block)
end
#...
end
```
{% endcode %}
which then allows you to call the card component like `card(title: "foo", body: "bar")` if the above shown module is included properly.
As this is just a plain Ruby module, you need to include it in all contexts you want to use the alias method. It might be a good idea to create your own `ApplicationPage`, `ApplicationComponent` and `ApplicationLayout` as base classes for your pages, components ans layouts. In there, you include your component registry module(s) only once and have access to the alias methods in all child classes:
{% code title="app/matestack/application_page.rb" %}
```ruby
class ApplicationPage < Matestack::Ui::Page
include Components::Registry
end
```
{% endcode %}
{% code title="app/matestack/application_component.rb" %}
```ruby
class ApplicationComponent < Matestack::Ui::Component
include Components::Registry
end
```
{% endcode %}
{% code title="app/matestack/application_layout.rb" %}
```ruby
class ApplicationLayout < Matestack::Ui::Layout
include Components::Registry
end
```
{% endcode %}
================================================
FILE: docs/components/usage-in-isolation.md
================================================
# Usage in Isolation
================================================
FILE: docs/components/usage-on-matestack-layouts.md
================================================
# Usage on Matestack Layouts
================================================
FILE: docs/components/usage-on-matestack-pages.md
================================================
# Usage on Matestack Pages
================================================
FILE: docs/components/usage-on-rails-views.md
================================================
# Components on Rails views
If you already have plenty of Rails views \(ERB, Haml or Slim\) and want to start creating small UI components in pure Ruby, you are able to use components on these existing views.
{% code title="app/matestack/components/products/teaser.rb" %}
```ruby
class Components::Products::Teaser < Matestack::Ui::Component
requires :product
def response
a path: product_path(context.product), class: 'product-teaser' do
div do
h2 context.product.name
paragraph conext.product.description
b context.product.price
end
end
end
end
```
{% endcode %}
The class is then called on your Rails view, in this case an ERB view:
```markup
<%= @products.each do |product| %>
<%= Components::Products::Teaser.(product: product) %>
<% end %>
```
{% hint style="info" %}
This approach is suitable for existing apps and a good idea to migrate to Matestack step by step. If you start with a blank Rails app, we recommend to go full Matestack right away**!**
{% endhint %}
================================================
FILE: docs/getting-started/hello-world.md
================================================
# Hello World
WIP!
================================================
FILE: docs/getting-started/installation-update.md
================================================
# Installation & Update
## Installation
Add 'matestack-ui-core' to your Gemfile
```ruby
gem 'matestack-ui-core'
```
and run
```
$ bundle install
```
### Matestack folder
Create a folder called `matestack` in your app directory. All your Matestack layouts, pages and components will be defined there.
```
$ mkdir app/matestack
```
### Controller setup
Add the Matestack helper to your controllers. If you want to make the helpers available in all controllers, add it to your `ApplicationController` :
`app/controllers/application_controller.rb`
```ruby
class ApplicationController < ActionController::Base
include Matestack::Ui::Core::Helper
#...
end
```
Now, you are able to create UI components in pure Ruby and use them in your Rails views. Additionally you can substitute Rails views and layouts with Matestack pages and layouts.
## Update
### Ruby Gem
Depending on the entry in your Gemfile, you might need to adjust the allowed version ranges in order to update the Gem. After checked and adjusted the version ranges, run:
```bash
bundle update matestack-ui-core
```
and then check the installed version:
```bash
bundle info matestack-ui-core
```
================================================
FILE: docs/html-rendering/html-rendering.md
================================================
# Basic Rendering Mechanism
Matestack’s rendering mechanism takes care of converting Ruby into HTML:
```ruby
div class: "card shadow-sm border-0 bg-light", foo: "bar" do
img path: "...", class: "w-100"
div class: "card-body" do
h5 "foo", class: "card-title"
paragraph "bar", class: "card-text"
end
end
```
will be rendered to:
```markup
<div class="card shadow-sm border-0 bg-light" foo="bar">
<img src="..." class="w-100">
<div class="card-body">
<h5 class="card-title">foo</h5>
<p class="card-text">bar</p>
</div>
</div>
```
That's working because `matestack-ui-core` defines all kind of Ruby methods targeting Rails ActionView `tag` helper, rendering the desired HTML tag and content as a String. This enables you to build a well known DOM structure while writing and utilizing pure Ruby!
As you can see, you can add CSS classes and ids as well as custom tag attributes. This way `matestack-ui-core` can be combined with various [CSS frameworks](broken-reference), your custom styles and all kinds of reactivity systems. 
It’s already fun to write pure Ruby instead of HTML or any other templating engine syntax but this approach is really paying of, when you start using Ruby's language features in order to split your UI implementation into various small chunks, organized through included modules, class inheritance or simply multiple Ruby methods within one class!
{% hint style="info" %}
The above shown Ruby code lives in Ruby classes inheriting from `Matestack::Ui::Component`, `Matestack::Ui::Page` or Matestack::Ui::Layout - they are described in the following sections of these docs and might look like this:
```ruby
class Components::HelloWorld < Matestack::Ui::Component
def response
div class: "my-class" do
plain "hello world!"
end
end
end
```
{% endhint %}
## Supported HTML Tags
### Void Tags
These tags by definition do not allow an inner HTML and therefore do not take an block but all kinds of tag attributes, e.g.:
```ruby
# ...
hr class: "some-class"
# ...
```
* area
* base
* br
* col
* hr
* img | _you can use `src` or `path` in order to reference the url to the image_
* input
* link
* meta
* param
* command
* keygen
* source
### Tags
The following tags take content via a block OR first (non-hash) argument and all kind of tag attributes, e.g.:
```ruby
# define inner HTML via a block
span class: "some-class" do
plain "foo"
end
# OR: define inner HTML via a simple first non-hash argument
span "foo", class: "some-class"
# ...
```
* a | _you can use `href` or `path` in order to reference the url of the link_
* abbr
* acronym
* address
* applet
* article
* aside
* audio
* b
* base
* basefont
* bdi
* bdo
* big
* blockquote
* body
* button
* canvas
* caption
* center
* cite
* code
* col
* colgroup
* data
* datalist
* dd
* del
* details
* dfn
* dialog
* dir
* div
* dl
* dt
* em
* embed
* fieldset
* figcaption
* figure
* font
* footer
* form
* frame
* frameset
* h1 | _also available via `heading size: 1`_
* h2 | _also available via `heading size: 2`_
* h3 | _also available via `heading size: 3`_
* h4 | _also available via `heading size: 4`_
* h5 | _also available via `heading size: 5`_
* h6 | _also available via `heading size: 6`_
* head
* header
* html
* i
* iframe
* ins
* kbd
* label
* legend
* li
* main
* map
* mark
* meter
* nav
* noframes
* noscript
* object
* ol
* optgroup
* option
* output
* paragraph | _p is not working as it's an alias for puts in Ruby core_
* picture
* pre
* progress
* q
* rp
* rt
* ruby
* s
* samp
* script
* section
* select
* small
* span
* strike
* strong
* style
* sub
* summary
* sup
* svg
* table
* tbody
* td
* template
* textarea
* tfoot
* th
* thead
* time
* title
* tr
* track
* tt
* u
* ul
* var
* video
* wbr
## Text Rendering
In order to render plain text, do:
```ruby
#...
plain "hello world!"
# "hello world!" alone would not be rendered!
#...
```
## Tag/Data Attributes
Matestack's rendering mechanism automatically renders all given options as tag attributes. For convenience, data attributes can be passend in within a data hash:
```ruby
div class: "foo", id: "bar", hello: "world", data: { foo: "bar" } do
#...
end
```
```markup
<div class="foo" id="bar" hello="world" data-foo="bar">
<!-- ... -->
</div>
```
## Custom HTML Tags
If you want to use HTML tags which are not supported by Matestack's rendering mechanism by default, you can call ActionView's `tag` helper manually:
[https://apidock.com/rails/ActionView/Helpers/TagHelper/tag](https://apidock.com/rails/ActionView/Helpers/TagHelper/tag)
```ruby
plain tag.xyz("foo")
```
will render:
```markup
<xyz>foo</xyz>
```
================================================
FILE: docs/html-rendering/integrating-action-view-helpers.md
================================================
# Integrating Action View Helpers
Using Rails view helpers ([https://api.rubyonrails.org/classes/ActionView/Helpers.html](https://api.rubyonrails.org/classes/ActionView/Helpers.html)) in components, pages and layouts is supported when using the approaches shown below;
## Helpers without a block
Simple Action View helpers working without a block, can easily be integrated in a Matestack class response by calling `plain`:
```ruby
def response
plain t("my.locale")
# ...
plain link_to "Show", post_path(@post)
# ...
plain my_own_view_helper_method
# ...
plain any_method_returning_a_string
end
```
## Helpers yielding a block
If you want to use a helper like `form_for` you have to follow following approach:
```ruby
def response
# ...
plain do # <-- add this
form_with url: "/some_path" do |f|
matestack_to_s do # <-- add this, which converst following block to a string
plain f.text_field :foo # <-- call plain here again
br
div class: "some-input-wrapper" do
plain f.text_field :bar
end
br
plain f.submit
end
end
end
# ...
plain do
link_to root_path do
matestack_to_s do
div class: "some-link-wrapper" do
plain "foo from block"
end
end
end
end
# ...
# Code below will not work!
plain link_to root_path do
matestack_to_s do
div class: "some-link-wrapper" do
plain "foo from block"
end
end
end
end
```
{% hint style="info" %}
A component needs to be called in context of a controller (with included `Matestack::Ui::Core::Helper`), which is true when you're calling components from Rails views or on Matestack Pages/Layouts (which are themselves called by a controller normally).
When calling a component in isolation (which is possible), the view helpers might not work properly, especially when (implicitly) requiring a request object!
{% endhint %}
{% hint style="info" %}
We're currently working on an improved way to integrate ActionView Helpers which will enable removing the `plain` calls from your code.
{% endhint %}
================================================
FILE: docs/html-rendering/reusing-views-or-partials.md
================================================
# Integrating Rails Views or Partials
Matestack `rails_render` component offers the possibility to render a view or partial by passing its name and required params to it.
## Components reusing partials
Imagine the partial `app/views/products/_teaser.html.erb` containing following content:
```markup
<%= link_to product_path(product), class: 'product-teaser' do %>
<div>
<h2><%= product.name %></h2>
<p><%= product.description %></p>
<b><%= product.price %></b>
</div>
<% end %>
```
```ruby
class Components::Products::Trending < Matestack::Ui::Component
def prepare
@products = Product.where(trending: true)
end
def response
h1 'Trending products'
@products.each do |product|
rails_render partial: '/products/teaser', locals: { product: product }
end
end
end
```
As you see, we used the `rails_render` component here to render our products teaser partial. Given the string rails searches for a partial in `app/views/products/_teaser.html.erb`. As our product teaser partial uses a `product` we pass in a product as a `local`.
`rails_render` works with ERB, Haml and Slim Templates, as long as you have installed and configured the desired templating engine correctly in your Rails app.
## Components reusing views
As mentioned above the `rails_render` component can not only render partials but also views. Following Rails view can be reused within a Matestack component:
`app/views/static/index.html.erb`
```markup
<main>
<%= render partial: 'products/teaser', collection: products, as: :product %>
</main>
<div>
<%= link_to 'All products', products_path %>
</div>
```
```ruby
class Components::Products::Index < Matestack::Ui::Component
def prepare
@products = Product.where(trending: true)
end
def response
rails_render template: '/static/index', locals: { products: @products }
end
end
```
================================================
FILE: docs/layouts/api.md
================================================
# API
A layout class defines a layout within its `response` method and is suppose to yield the content of a page.
## Response
Use the `response` method to define the UI of the app by using Matestack's HTML rendering and optionally calling components.
```ruby
class SomeApp < Matestack::Ui::App
def response
nav do
a path: some_rails_path, text: "Navigate!"
end
main do
yield
end
footer do
div id: "div-on-app" do
SomeComponent.()
end
end
end
end
```
## Partials and helper methods
Use partials to keep the code dry and indentation layers manageable!
### Local partials on page level
In the page definition, see how this time from inside the response, the `my_partial` method below is called:
```ruby
class SomeApp < Matestack::Ui::App
def response
nav do
a path: some_rails_path, text: "Navigate!"
end
main do
yield
end
footer do
div id: "div-on-app" do
SomeComponent.()
end
my_partial "foo from app"
end
end
private # optionally mark your partials as private
def my_partial text
div class: "nested" do
plain text
end
end
end
```
### Partials defined in modules
Extract code snippets to modules for an even better project structure. First, create a module:
```ruby
module MySharedPartials
def my_partial text
div class: "nested" do
plain text
end
end
end
```
Include the module in the page:
```ruby
class SomeApp < Matestack::Ui::App
include MySharedPartials
def response
nav do
a path: some_rails_path, text: "Navigate!"
end
main do
yield
end
footer do
div id: "div-on-app" do
SomeComponent.()
end
my_partial "foo from app"
end
end
end
```
### Helper methods
Not only can instance methods be used as "partials" but as general helpers performing any kind of logic or data resolving:
```ruby
class SomeApp < Matestack::Ui::App
def response
nav do
a path: some_rails_path, text: "Navigate!"
end
main do
if is_admin?
yield
else
plain "not authorized"
end
end
end
private # optionally mark your helper methods as private
def is_admin?
true # some crazy Ruby logic!
end
end
```
## Prepare
Use a prepare method to resolve instance variables before rendering a page if required.
```ruby
class SomeApp < Matestack::Ui::App
def prepare
@heading = "Foo"
end
def response
h1 @heading
nav do
a path: some_rails_path, text: "Navigate!"
end
main do
yield
end
end
end
```
## Params access
An app can access request information, e.g. url query params, by calling the `params` method:
```ruby
class SomeApp < Matestack::Ui::App
def response
nav do
a path: some_rails_path, text: "Navigate!"
end
main do
plain params[:foo] # "bar"
yield
end
end
end
```
Now, visiting the respective route to the page, e.g. via `/xyz?foo=bar`, the page reads the `[:foo]` from the params and displays it.
================================================
FILE: docs/layouts/rails-controller-integration.md
================================================
# Rails Controller Integration
Just like a Rails layout would yield a Rails view, a Matestack layout yields a Matestack page. The layout uses Matestack's HTML rendering mechanism in a `response` method and may additionally call other components in order to define a specific UI.
{% code title="app/matestack/some_app/some_layout.rb" %}
```ruby
class SomeApp::SomeLayout < Matestack::Ui::Layout
def response
h1 "Some App"
main do
yield
end
end
end
```
{% endcode %}
In this basic example the layout is using the methods `h1` and `main` in order to create the markup as well as a `yield` in order to yield a page on a specific position.
{% hint style="info" %}
A Matestack layout itself will be yielded into the Rails layout, unless the Rails layout is disabled in the controller via:`layout false`
{% endhint %}
Usually a layout implies a specific context of your application. Multiple pages are then scoped within that context, which could lead to a file structure like:
```bash
app/matestack/
|
└───some_app/
│ │ some_layout.rb
│ └───pages/
│ │ │ page1.rb
│ │ │ page2.rb
│ │ │ page3.rb
```
and then used in a controller like this:
### Feature walk-through
#### 1. Create UI components in pure Ruby
Craft your UI based on your components written in pure Ruby. Utilizing Ruby's amazing language features, you're able to create a cleaner and more maintainable UI implementation.
**Implement UI components in pure Ruby**
Create Ruby classes within your Rails project and call Matestack's core components through a Ruby DSL in order to craft your UIs. The Ruby method "div" for example calls one of the static core components, responsible for rendering HTML tags. A component can take Strings, Integers Symbols, Arrays or Hashes (...) as optional properties (e.g. "title") or require them (e.g. "body").
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::Component
required :body
optional :title
optional :image
def response
div class: "card shadow-sm border-0 bg-light" do
img path: context.image, class: "w-100" if context.image.present?
div class: "card-body" do
h5 context.title if context.title.present?
paragraph context.body, class: "card-text"
end
end
end
end
```
**Use your Ruby UI components on your existing Rails views**
Components can be then called on Rails views (not only! see below), enabling you to create a reusable card components, abstracting UI complexity in your own components.
`app/views/your_view.html.erb`
```erb
<!-- some other erb markup -->
<%= Components::Card.call(title: "hello", body: "world") %>
<!-- some other erb markup -->
```
**Use Ruby methods as partials**
Split your UI implementation into multiple small chunks helping others (and yourself) to better understand your implementation. Using this approach helps you to create a clean, readable and maintainable codebase.
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::Component
required :body
optional :title
optional :image
optional :footer
def response
div class: "card shadow-sm border-0 bg-light" do
img path: context.image, class: "w-100" if context.image.present?
card_content
card_footer if context.footer.present?
end
end
def card_content
div class: "card-body" do
h5 context.title if context.title.present?
paragraph context.body, class: "card-body"
end
end
def card_footer
div class: "card-footer text-muted" do
plain footer
end
end
end
```
`app/views/your_view.html.erb`
```erb
<!-- some other erb markup -->
<%= Components::Card.call(title: "hello", body: "world", footer: "foo") %>
<!-- some other erb markup -->
```
**Use class inheritance**
Because it's just a Ruby class, you can use class inheritance in order to further improve the quality of your UI implementation. Class inheritance can be used to easily create variants of UI components but still reuse parts of the implementation.
`app/matestack/components/blue_card.rb`
```ruby
class Components::BlueCard < Components::Card
def response
div class: "card shadow-sm border-0 bg-primary text-white" do
img path: context.image, class: "w-100" if context.image.present?
card_content #defined in parent class
card_footer if context.footer.present? #defined in parent class
end
end
end
```
`app/views/your_view.html.erb`
```erb
<!-- some other erb markup -->
<%= Components::BlueCard.call(title: "hello", body: "world") %>
<!-- some other erb markup -->
```
**Use components within components**
Just like you used matestack's core components on your own UI component, you can use your own UI components within other custom UI components. You decide when using a Ruby method partial should be replaced by another self contained UI component!
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::Component
required :body
optional :title
optional :image
def response
div class: "card shadow-sm border-0 bg-light" do
img path: context.image, class: "w-100" if context.image.present?
# calling the CardBody component rather than using Ruby method partials
Components::CardBody.call(title: context.title, body: context.body)
end
end
end
```
`app/matestack/components/card_body.rb`
```ruby
class Components::CardBody < Matestack::Ui::Component
required :body
optional :title
def response
# Just an example. Would make more sense, if this component had
# a more complex structure
div class: "card-body" do
h5 context.title if context.title.present?
paragraph context.body, class: "card-body"
end
end
end
```
**Yield components into components**
Sometimes it's not enough to just pass simple data into a component. No worries! You can just yield a block into your components! Using this approach gives you more flexibility when using your UI components. Ofcourse yielding can be used alongside passing in simple params.
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::Component
required :body
optional :title
optional :image
def response
div class: "card shadow-sm border-0 bg-light" do
img path: context.image, class: "w-100" if context.image.present?
Components::CardBody.call() do
# yielding a block into the card_body component
h5 context.title if context.title.present?
paragraph context.body, class: "card-body"
end
end
end
end
```
`app/matestack/components/card_body.rb`
```ruby
class Components::CardBody < Matestack::Ui::Component
def response
# Just an example. Would make more sense, if this component had
# a more complex structure
div class: "card-body" do
yield if block_given?
end
end
end
```
**Use named slots for advanced content injection**
If you need to inject multiple blocks into your UI component, you can use "slots"! Slots help you to build complex UI components with multiple named content placeholders for highest implementation flexibility!
`app/matestack/components/card.rb`
```ruby
class Components::Card < Matestack::Ui::Component
required :body
optional :title
optional :image
def response
div class: "card shadow-sm border-0 bg-light" do
img path: context.image, class: "w-100" if context.image.present?
Components::CardBody.call(slots: {
heading: method(:heading_slot),
body: method(:body_slot)
})
end
end
def heading_slot
h5 context.title if context.title.present?
end
def body_slot
paragraph context.body, class: "card-body"
end
end
```
`app/matestack/components/card_body.rb`
```ruby
class Components::CardBody < Matestack::Ui::Component
required :slots
def response
# Just an example. Would make more sense, if this component had
# a more complex structure
div class: "card-body" do
div class: "heading-section" do
slot :heading
end
div class: "body-section" do
slot :body
end
end
end
end
```
#### 2. Substitute Rails Views with Matestack Pages
Until here we used Matestack components on Rails views. If desired you can go one step further and use Matestack components on something called a Matestack Page:
A Matestack page can be compared to a Rails view and might be yielded within a layout provided by an associated Matestack layout class (see below). The page itself uses Matestack's HTML rendering mechanism in a `response` method and may additionally call other components in order to define a specific UI.
{% code title="app/matestack/pages/some_page.rb" %}
```ruby
class Pages::SomePage < Matestack::Ui::Page
def response
div class: "container" do
span id: "hello" do
plain "hello world!"
end
Components::Card.call(title: "foo", body: "bar")
end
end
end
```
{% endcode %}
Pages are used as Rails view substitutes and therefore called in a Rails controller action:
{% code title="app/controllers/some_controller.rb" %}
```ruby
class SomeController < ApplicationController
include Matestack::Ui::Core::Helper
def overview
render Pages::SomePage
end
end
```
{% endcode %}
The page response - in this case - will be yielded into the Rails layout if not specified differently.
#### 3. Wrap Matestack Pages in Matestack Layouts
Just like a Rails layout would yield a Rails view, a Matestack layout yields a Matestack page. The layout uses Matestack's HTML rendering mechanism in a `response` method and may additionally call other components in order to define a specific UI.
{% code title="app/matestack/some_app/some_layout.rb" %}
```ruby
class SomeApp::SomeLayout < Matestack::Ui::Layout
def response
h1 "Some App"
main do
yield
end
end
end
```
{% endcode %}
In this basic example the layout is using the methods `h1` and `main` in order to create the markup as well as a `yield` in order to yield a page on a specific position.
{% hint style="info" %}
A Matestack layout itself will be yielded into the Rails layout, unless the Rails layout is disabled in the controler via:`layout false`
{% endhint %}
Usually a layout implies a specific context of your application. Multiple pages are then scoped within that context, which could lead to a file structure like:
```bash
app/matestack/
|
└───some_app/
│ │ some_layout.rb
│ └───pages/
│ │ │ page1.rb
│ │ │ page2.rb
│ │ │ page3.rb
```
and then used in a controller like this:
{% code title="app/controllers/some_controller.rb" %}
```ruby
class SomeController < ApplicationController
include Matestack::Ui::Core::Helper
matestack_layout SomeApp::SomeLayout
def page_1
render SomeApp::Pages::Page1
end
def page_2
render SomeApp::Pages::Page2
end
def page_3
render SomeApp::Pages::Page3, matestack_layout: false # skip app layout on this page
end
end
```
{% endcode %}
================================================
FILE: docs/migrate-from-2.x-to-3.0.md
================================================
# Migrating from 2.x to 3.0
## Core/VueJs repo and gem split
* `matestack-ui-core` previously contained logic for
* Ruby -> HTML conversion
* Reactivity via prebuilt and custom Vue.js components
* in order to have better seperation of concerns, we've moved the reactivity related things to its own repository/gem -> `matestack-ui-vue_js`
* `matestack-ui-core` is now meant to be combined with any reactivity framework or none at all
{% hint style="warning" %}
**Please follow the migration guide within the docs of `matestack-ui-vuejs` when using reactivity features of `matestack-ui-core` 2.x**
{% endhint %}
## Remove `matestack-ui-core` JavaScript package
- `matestack-ui-core` does not ship a JavaScript package anymore
- please remove the package from your application and switch to `matestack-ui-vuejs` for the VueJs driven reactivity if required
```
yarn remove matestack-ui-core
```
## `Matestack::Ui::App` is now called `Matestack::Ui::Layout`
* `Matestack::Ui::App` was always meant to be a layout wrapping pages, but was supercharged with some vuejs logic before splitting the `core` and `vuejs` repos
* now `Matestack::Ui::App` is only a layout, that's why it should be named like that: `Matestack::Ui::Layout`
\-> Search\&Replace
## `matestack_app` method is renamed to `matestack_layout`
* following the above mentioned naming adjustment, the `matestack_app` method used on controller level is renamed to `matestack_layout`
`app/controllers/demo_controller.rb`
```ruby
class DemoController < ActionController::Base
include Matestack::Ui::Core::Helper
layout "application" # root rails layout file
matestack_layout DemoApp::Layout # <-- renamed from matestack_app
def foo
render DemoApp::Pages::Foo
end
end
```
\-> Search\&Replace
## `Matestack::Ui::Layout` `Matestack::Ui::Page` wrapping DOM structures
* previously, `Matestack::Ui::App` added some wrapping DOM structure around the whole layout and around it's `yield`
* this enabled dynamic page transition and loading state animations
* `Matestack::Ui::Layout` now purely renders the layout and yields a page without anything in between
* the wrapping DOM structres required for dynamic page transitions and loading state animations needs to be added via two new components if you want to use these features via `matestack-ui-vue_js` (see section below!)
`matestack/some/app/layout.rb`
```ruby
class Some::App::Layout < Matestack::Ui::Layout
def response
h1 "Demo App"
main do
yield
end
end
end
```
`matestack/some/app/pages/some_page.rb`
```ruby
class Some::App::Pages::SomePage < Matestack::Ui::Page
def response
h2 "Some Page"
end
end
```
will just render:
```html
<body> <!-- coming from rails layout if specified -->
<!-- no wrapping DON structure around the layout -->
<h1>Demo App</<h1>
<main>
<!-- page markup without any wrapping DOM structure -->
<h2>Some Page</h2>
<main>
</body>
```
\-> Adjust CSS if you have created any rules targeting the wrapping DOM structure which now only is applied when using components from `matestack-ui-vuejs` explicitly
================================================
FILE: docs/pages/api.md
================================================
# Page API
## Response
Use the `response` method to define the UI of the page by using Matestack's HTML rendering or calling components.
```ruby
class SomePage < Matestack::Ui::Page
def response
div id: "div-on-page" do
SomeComponent.()
end
end
end
```
```ruby
class SomeComponent < Matestack::Ui::Component
def response
div id: "my-component" do
plain "hello world!"
end
end
end
```
## Partials and helper methods
Use partials to keep the code dry and indentation layers manageable!
### Local partials on page level
In the page definition, see how this time from inside the response, the `my_partial` method below is called:
```ruby
class SomePage < Matestack::Ui::Page
def response
div id: "my-page" do
my_partial "foo from page"
end
end
private # optionally mark your partials as private
def my_partial text
div class: "nested"
plain text
end
end
end
```
### Partials defined in modules
Extract code snippets to modules for an even better project structure. First, create a module:
```ruby
module MySharedPartials
def my_partial text
div class: "nested"
plain text
end
end
end
```
Include the module in the page:
```ruby
class SomePage < Matestack::Ui::Page
include MySharedPartials
def response
div id: "my-page" do
my_partial "foo from component"
end
end
end
```
### Helper methods
Not only can instance methods be used as "partials" but as general helpers performing any kind of logic or data resolving:
```ruby
class SomePage < Matestack::Ui::Page
def response
div id: "my-page" do
if is_admin?
latest_users.each do |user|
div do
plain user.name # ...
end
end
else
plain "not authorized"
end
end
end
private # optionally mark your helper methods as private
def is_admin?
true # some crazy Ruby logic!
end
def latest_users
User.last(10) # calling ActiveRecord models for example
end
end
```
## Prepare
Use a prepare method to resolve instance variables before rendering a page if required.
```ruby
class SomePage < Matestack::Ui::Page
def prepare
@some_data = "some data"
end
def response
div id: "my-page" do
plain @some_data
end
end
end
```
## Params access
A page can access request information, e.g. url query params, by calling the `params` method:
```ruby
class SomePage < Matestack::Ui::Page
def response
div id: "my-page" do
plain params[:foo]
end
end
end
```
Now, visiting the respective route to the page, e.g. via `/xyz?foo=bar`, the page reads the `[:foo]` from the params and displays it.
## Passing data to pages
Sometimes you want to pass in data from the calling controller action into the page. This works the same way as seen at components:
```ruby
class SoomeController < ActionController::Base
include Matestack::Ui::Core::Helper
def some_page
render SomePage, foo: 'bar', bar: 'baz'
end
end
```
```ruby
class SomePage < Matestack::Ui::Page
required :foo
optional :bar
def response
div id: "my-page" do
plain context.foo # "bar"
plain context.bar # "baz"
end
end
end
```
================================================
FILE: docs/pages/rails-controller-integration.md
================================================
# Rails Controller Integration
Pages are used as Rails view substitutes and therefore called in a Rails controller action:
{% code title="app/controllers/some_controller.rb" %}
```ruby
class SomeController < ApplicationController
include Matestack::Ui::Core::Helper
def overview
render Pages::SomePage
end
end
```
{% endcode %}
{% hint style="info" %}
A Matestack page will in this case be yielded into the Rails layout, unless the Rails layout is disabled in the controller via:`layout false`
{% endhint %}
## Passing data to pages
Sometimes you want to pass in data from the calling controller action into the page. This works the same way as seen at components:
```ruby
class SomeController < ActionController::Base
include Matestack::Ui::Core::Helper
def some_page
render SomePage, foo: 'bar', bar: 'baz'
end
end
```
```ruby
class SomePage < Matestack::Ui::Page
required :foo
optional :bar
def response
div id: "my-page" do
plain context.foo # "bar"
plain context.bar # "baz"
end
end
end
```
================================================
FILE: entrypoint.sh
================================================
#!/bin/bash
set -e
if [[ ! -e /app/Gemfile.lock ]]; then
bundle install
fi
# Remove a potentially pre-existing server.pid for Rails.
rm -f /app/tmp/pids/server.pid
# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
================================================
FILE: lib/matestack/ui/component.rb
================================================
Matestack::Ui::Component = Matestack::Ui::Core::Component
================================================
FILE: lib/matestack/ui/core/base.rb
================================================
require_relative 'tag_helper'
module Matestack
module Ui
module Core
class Base
include ActionView::Helpers::TagHelper
include Matestack::Ui::Core::Properties
include Matestack::Ui::Core::TagHelper
attr_accessor :html_tag, :text, :options, :parent, :escape, :bind_to_parent
def initialize(html_tag = nil, text = nil, options = {}, &block)
return unless render?
if options && options[:detach_from_parent] == true
self.bind_to_parent = false
else
self.bind_to_parent = ([:without_parent].include?(html_tag) ? false : true)
end
self.slots = self.options.delete(:slots) if self.options
# extract_options(text, options) is called in properties
self.html_tag = html_tag if self.bind_to_parent
self.escape = self.options.delete(:escape) || true
self.parent = Matestack::Ui::Core::Context.parent
self.parent.children << self if self.parent if self.bind_to_parent
self.prepare
Matestack::Ui::Core::Context.parent = self
create_children(&block)
Matestack::Ui::Core::Context.parent = self.parent
self
end
# can be optionally overwritten in subclass
# in order to conditionally render the component
def render?
true
end
# check if text is given and set text and options accordingly
def extract_options(text, options)
if text.is_a? Hash
# we need to dup the text object because we're deleting keys from this object which manipulates the object passed in here
# if this object is reused after beeing injected into this component, the keys would be missing
self.options = text.dup
else
self.text = text
# we need to dup the options object because we're deleting keys from this object which manipulates the object passed in here
# if this object is reused after beeing injected into this component, the keys would be missing
self.options = options.dup || {}
end
self.options.symbolize_keys!
end
def prepare
# can be optionally overwritten in subclass in order to set
# instance vars for example, might get deprecated in the future
end
# create child items by either running the response method if exists or executing the block
# overwrite if needed (like in pages or apps)
def create_children(&block)
if respond_to?(:response)
self.response &block
else
block.call if block_given?
end
end
def self.call(text = nil, options = {}, &block)
self.new(nil, text, options, &block).render_content
end
def children
@children ||= []
end
def render_content
if children.empty?
child_content = self.escape ? ERB::Util.html_escape(text) : text if text
else
# using "\n" in order to preserve the 1.x rendering behavior which impacts appearance in browser
child_content = (children.map { |child| " \n " + child.render_content }.join + " \n ").html_safe
end
result = ''
if self.html_tag
result = tag.public_send(self.html_tag, child_content, **self.options || {})
elsif child_content
result = child_content
end
result
end
def params
Matestack::Ui::Core::Context.params || ActionController::Parameters.new({})
end
def view_context
if Matestack::Ui::Core::Context.controller.nil?
Matestack::Ui::Core::Context.controller = ActionController::Base.new
else
Matestack::Ui::Core::Context.controller&.view_context
end
end
def method_missing(name, *args, **kwargs, &block)
if view_context && view_context.respond_to?(name, true)
view_context_response = view_context.send(name, *args, **kwargs, &block)
return view_context_response
end
if Rails.application.routes.url_helpers.respond_to?(name, true)
return Rails.application.routes.url_helpers.send(name, *args, &block)
end
return raise NameError, "#{name} is not defined for #{self.class}", caller
end
def to_str
render_content
end
alias to_s to_str
end
end
end
end
================================================
FILE: lib/matestack/ui/core/component.rb
================================================
module Matestack
module Ui
module Core
class Component < Base
end
end
end
end
================================================
FILE: lib/matestack/ui/core/context.rb
================================================
module Matestack
module Ui
module Core
class Context < ActiveSupport::CurrentAttributes
attribute :layout
attribute :parent
attribute :isolated_parent
attribute :params
attribute :controller
attribute :component_block
attribute :async_components
end
end
end
end
================================================
FILE: lib/matestack/ui/core/helper.rb
================================================
module Matestack
module Ui
module Core
module Helper
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def inherited(subclass)
subclass.matestack_layout(@matestack_layout)
super
end
def matestack_layout(layout = nil)
@matestack_layout = layout ? layout : @matestack_layout
end
end
def render(*args)
setup_context
if args.first.is_a?(Class) && args.first.ancestors.include?(Base)
raise 'expected a hash as second argument' unless args.second.is_a?(Hash) || args.second.nil?
begin
controller_layout = self.class.send(:_layout)
rescue
controller_layout = nil
end
options = args.second || {}
layout = options.delete(:matestack_layout) || self.class.matestack_layout
page = args.first
if controller_layout == false
root_layout = layout ? layout.layout : false
else
# when using the turbo-rails gem, controller_layout is a Proc
# https://github.com/hotwired/turbo-rails/blob/v1.0.1/app/controllers/turbo/frames/frame_request.rb#L16
# and not nil or a string indicating which layout to be used like before
if controller_layout.nil? || controller_layout.is_a?(Proc)
root_layout = "application"
else
root_layout = controller_layout
end
end
if layout && params[:only_page].nil? && params[:component_key].nil? && params[:component_class].nil?
render_layout layout, page, options, root_layout
else
if params[:component_key] && params[:component_class].nil?
render_component layout, page, params[:component_key], options
elsif params[:component_class]
if params[:component_key]
render_component nil, params[:component_class].constantize, params[:component_key], JSON.parse(params[:public_options] || '{}')
else
render html: params[:component_class].constantize.(public_options: JSON.parse(params[:public_options] || '{}'))
end
else
if params[:only_page]
render_page page, options, false
else
render_page page, options, root_layout
end
end
end
else
super
end
end
def render_layout(layout, page, options, root_layout)
render html: layout.new(options) { page.new(options) }.render_content.html_safe, layout: root_layout
end
def render_page(page, options, root_layout)
render html: page.new(options).render_content.html_safe, layout: root_layout
end
def render_component(layout, page, component_key, options)
layout ? layout.new(options) { page.new(options) } : page.new(options) # create page structure in order to later access registered async components
render html: Matestack::Ui::Core::Context.async_components[component_key].render_content.html_safe, layout: false
end
def setup_context
Matestack::Ui::Core::Context.params = self.params
Matestack::Ui::Core::Context.controller = (self.class <= ActionController::Base) ? self : @_controller
end
end
end
end
end
================================================
FILE: lib/matestack/ui/core/layout.rb
================================================
module Matestack
module Ui
module Core
class Layout < Base
def initialize(options = {})
@controller = Context.controller
Context.layout = self
super(nil, nil, options)
end
# layout class method to specify if a rails layout should be used
def self.inherited(subclass)
subclass.layout(@layout)
super
end
def self.layout(layout = nil)
@layout = layout ? layout : @layout
end
end
end
end
end
================================================
FILE: lib/matestack/ui/core/page.rb
================================================
module Matestack
module Ui
module Core
class Page < Base
def initialize(options = {})
super(nil, nil, options)
end
end
end
end
end
================================================
FILE: lib/matestack/ui/core/properties.rb
================================================
module Matestack
module Ui
module Core
module Properties
def self.included(base)
base.extend ClassMethods
base.send :prepend, Initializer
end
module Initializer
def initialize(html_tag = nil, text = nil, options = {}, &block)
extract_options(text, options)
create_context
set_text
super
end
end
module ClassMethods
extend Gem::Deprecate
def required(*args)
@required = (@required || []).concat(args)
end
alias requires required
def optional(*args)
@optional = (@optional || []).concat(args)
end
def required_property_keys
@required
end
def optional_property_keys
@optional
end
def inherited(subclass)
subclass.required(*required_property_keys)
subclass.optional(*optional_property_keys)
super
end
end
def context
@context ||= OpenStruct.new
end
alias :ctx :context
def required_property_keys
self.class.required_property_keys || []
end
def optional_property_keys
self.class.optional_property_keys || []
end
def create_context
create_context_for_properties(self.required_property_keys, required: true)
create_context_for_properties(self.optional_property_keys)
end
def create_context_for_properties(properties, required: false)
properties.uniq.each do |property|
if property.is_a? Hash
property.each do |key, value|
method_name = value[:as] || key
raise "required property '#{key}' is missing for '#{self.class}'" if required && self.options[key].nil?
context.send(:"#{method_name}=", self.options.delete(key))
end
else
raise "required property '#{property}' is missing for '#{self.class}'" if required && self.options[property].nil?
context.send(:"#{property}=", self.options.delete(property))
end
end if properties
end
def set_text
# the text property is treated specially since 2.0.0 enables text injection for all components like:
#
# some_component "foo", class: "whatever" -> self.text -> "foo"
#
# prior to 2.0.0, text injection happened like that:
#
# some_component text: "foo", class: "whatever" -> self.options[:text] -> "foo"
#
# in both cases "foo" should be available via self.context.text AND self.text
#
# in 2.0.0 text is available via context.text if text is marked as required or optional
# in order to have a consistent access, we make this text accessable via self.text as well in this case
# in all cases, text is accessable via self.text AND self.context.text
# we make the passed in text option available via context.text by default, even if not marked as required or optional
#
# additionally we need to delete text from the options, as they might be used to be rendered as
# tag attributes without any whitelisting as happened prior to 2.0.0
self.text = self.options.delete(:text) if self.options.has_key?(:text)
self.context.text = self.text
end
end
end
end
end
================================================
FILE: lib/matestack/ui/core/slots.rb
================================================
module Matestack
module Ui
module Core
module Slots
attr_accessor :slots
def slot(key, *args)
slots[key].call(*args)
end
end
end
end
end
================================================
FILE: lib/matestack/ui/core/tag_helper.rb
================================================
require_relative 'slots'
module Matestack
module Ui
module Core
module TagHelper
extend Gem::Deprecate
include Slots
# can't take content or a block
VOID_TAGS = %i[area base br col hr img input link meta param command keygen source]
TAGS = [:a, :abbr, :acronym, :address, :applet, :area, :article, :aside, :audio, :b, :base, :basefont, :bdi, :bdo, :big, :blockquote, :body, :br, :button, :canvas, :caption, :center, :cite, :code, :col, :colgroup, :data, :datalist, :dd, :del, :details, :dfn, :dialog, :dir, :div, :dl, :dt, :em, :embed, :fieldset, :figcaption, :figure, :font, :footer, :form, :frame, :frameset, :h1, :h2, :h3, :h4, :h5, :h6, :head, :header, :hr, :html, :i, :iframe, :img, :input, :ins, :kbd, :label, :legend, :li, :link, :main, :map, :mark, :meta, :meter, :nav, :noframes, :noscript, :object, :ol, :optgroup, :option, :output, :paragraph, :param, :picture, :pre, :progress, :q, :rp, :rt, :ruby, :s, :samp, :script, :section, :select, :small, :source, :span, :strike, :strong, :style, :sub, :summary, :sup, :svg, :table, :tbody, :td, :template, :textarea, :tfoot, :th, :thead, :time, :title, :tr, :track, :tt, :u, :ul, :var, :video, :wbr]
VOID_TAGS.each do |tag|
define_method tag do |options = {}|
Matestack::Ui::Core::Base.new(tag, nil, options)
end
end
TAGS.each do |tag|
define_method tag do |text = nil, options = {}, &block|
tag = :p if tag == :paragraph
Matestack::Ui::Core::Base.new(tag, text, options, &block)
end
end
def plain(text=nil, options=nil, &block)
if block_given?
Matestack::Ui::Core::Base.new(nil, yield, options)
else
Matestack::Ui::Core::Base.new(nil, text, options)
end
end
def unescape(text)
Matestack::Ui::Core::Base.new(nil, text&.html_safe, escape: false)
end
alias unescaped unescape
# override image in order to implement automatically using rails assets path
def img(text = nil, options = {}, &block)
# if :src attribut given try to replace automatically
if src = text.delete(:path)
text[:src] = ActionController::Base.helpers.asset_path(src)
end
Matestack::Ui::Core::Base.new(:img, text, options, &block)
end
def a(text = nil, options = {}, &block)
# if :path attribut given rename to href
if text.is_a?(Hash)
text[:href] = text.delete(:path) if text[:href].nil?
else
options[:href] = options.delete(:path) if options[:href].nil?
end
Matestack::Ui::Core::Base.new(:a, text, options, &block)
end
# support old heading component
def heading(text = nil, options=nil, &block)
if text.is_a?(Hash)
options = text
end
case options[:size]
when 1
h1(text, options, &block)
when 2
h2(text, options, &block)
when 3
h3(text, options, &block)
when 4
h4(text, options, &block)
when 5
h5(text, options, &block)
when 6
h6(text, options, &block)
else
h1(text, options, &block)
end
end
def rails_render(options = {})
plain render options
end
def detached(text=nil, options=nil, &block)
options = {} if options.nil?
options[:detach_from_parent] = true
Matestack::Ui::Core::Base.new(nil, text, options, &block)
end
def detached_to_s(text=nil, options=nil, &block)
detached(text, options, &block).to_str
end
alias matestack_to_s detached_to_s
end
end
end
end
================================================
FILE: lib/matestack/ui/core/version.rb
================================================
module Matestack
module Ui
module Core
VERSION = '3.0.1'
end
end
end
================================================
FILE: lib/matestack/ui/core.rb
================================================
base_path = 'matestack/ui/core'
require "#{base_path}/version"
module Matestack
module Ui
module Core
end
end
end
require "#{base_path}/context"
require "#{base_path}/properties"
require "#{base_path}/base"
require "#{base_path}/component"
require "#{base_path}/page"
require "#{base_path}/layout"
require "#{base_path}/helper"
# require abbreveations for apps, pages and components
require "matestack/ui/layout"
require "matestack/ui/page"
require "matestack/ui/component"
================================================
FILE: lib/matestack/ui/layout.rb
================================================
Matestack::Ui::Layout = Matestack::Ui::Core::Layout
================================================
FILE: lib/matestack/ui/page.rb
================================================
Matestack::Ui::Page = Matestack::Ui::Core::Page
================================================
FILE: matestack-ui-core.gemspec
================================================
$:.push File.expand_path("lib", __dir__)
# Maintain your gem's version:
require "matestack/ui/core/version"
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
s.name = "matestack-ui-core"
s.version = Matestack::Ui::Core::VERSION
s.authors = ["Jonas Jabari"]
s.email = ["jonas@matestack.io"]
s.homepage = "https://matestack.io"
s.summary = "Escape the frontend hustle & easily create interactive web apps in pure Ruby."
s.description = "Matestack provides a collection of open source gems made for Ruby on Rails developers. Matestack enables you to craft interactive web UIs without JavaScript in pure Ruby with minimum effort. UI code becomes a native and fun part of your Rails app."
s.license = "MIT"
s.metadata = { "source_code_uri" => "https://github.com/matestack/matestack-ui-core" }
s.files = Dir["{app,config,db,lib,vendor}/**/*", "LICENSE", "Rakefile", "README.md"]
s.add_dependency "rails", '>= 5.2'
end
================================================
FILE: results.txt
================================================
Capybara starting Puma...
* Version 4.3.5 , codename: Mysterious Traveller
* Min threads: 0, max threads: 4
* Listening on tcp://0.0.0.0:33123
.............................................................................................................................
Finished in 12.69 seconds (files took 2.38 seconds to load)
125 examples, 0 failures
Coverage report generated for Unit Tests to /app/coverage. 209 / 2187 LOC (9.56%) covered.
================================================
FILE: spec/core_spec_helper.rb
================================================
# This file was generated by the `rails generate rspec:install` command. Conventionally, all
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
# The generated `.rspec` file contains `--require spec_helper` which will cause
# this file to always be loaded, without a need to explicitly require it in any
# files.
#
# Given that it is always loaded, you are encouraged to keep this file as
# light-weight as possible. Requiring heavyweight dependencies from this file
# will add to the boot time of your test suite on EVERY test run, even for an
# individual file that may not need all of that loaded. Instead, consider making
# a separate helper file that requires the additional dependencies and performs
# the additional setup, and require it from the spec files that actually need
# it.
#
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
require 'simplecov'
SimpleCov.start do
enable_coverage :branch
add_filter "/spec"
add_filter %r{^/config/}
add_group "Concepts", "/app/concepts"
add_group "Helpers", "/app/helpers"
add_group "App Lib", "/app/lib"
add_group "Lib", %r{^/lib/}
track_files "{app,lib}/**/*.rb"
end
require 'webmock/rspec'
WebMock.allow_net_connect!
require File.join File.dirname(__FILE__), 'dummy', 'config', 'environment.rb'
Dir[File.join File.dirname(__FILE__), 'test', 'core', 'support', '**', '*.rb'].each { |f| require f }
require 'pry'
# require 'rspec/retry'
# require "rspec/wait"
RSpec.configure do |config|
# run retry only on features
# config.around :each, :js do |ex|
# ex.run_with_retry retry: 3
# end
# config.include Capybara::DSL
# rspec-expectations config goes here. You can use an alternate
# assertion/expectation library such as wrong or the stdlib/minitest
# assertions if you prefer.
config.expect_with :rspec do |expectations|
# This option will default to `true` in RSpec 4. It makes the `description`
# and `failure_message` of custom matchers include text for helper methods
# defined using `chain`, e.g.:
# be_bigger_than(2).and_smaller_than(4).description
# # => "be bigger than 2 and smaller than 4"
# ...rather than:
# # => "be bigger than 2"
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
# rspec-mocks config goes here. You can use an alternate test double
# library (such as bogus or mocha) by changing the `mock_with` option here.
config.mock_with :rspec do |mocks|
# Prevents you from mocking or stubbing a method that does not exist on
# a real object. This is generally recommended, and will default to
# `true` in RSpec 4.
mocks.verify_partial_doubles = true
end
# This option will default to `:apply_to_host_groups` in RSpec 4 (and will
# have no way to turn it off -- the option exists only for backwards
# compatibility in RSpec 3). It causes shared context metadata to be
# inherited by the metadata hash of host groups and examples, rather than
# triggering implicit auto-inclusion in groups with matching metadata.
config.shared_context_metadata_behavior = :apply_to_host_groups
# The settings below are suggested to provide a good initial experience
# with RSpec, but feel free to customize to your heart's content.
=begin
# This allows you to limit a spec run to individual examples or groups
# you care about by tagging them with `:focus` metadata. When nothing
# is tagged with `:focus`, all examples get run. RSpec also provides
# aliases for `it`, `describe`, and `context` that include `:focus`
# metadata: `fit`, `fdescribe` and `fcontext`, respectively.
config.filter_run_when_matching :focus
# Allows RSpec to persist some state between runs in order to support
# the `--only-failures` and `--next-failure` CLI options. We recommend
# you configure your source control system to ignore this file.
config.example_status_persistence_file_path = "spec/examples.txt"
# Limits the available syntax to the non-monkey patched syntax that is
# recommended. For more details, see:
# - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
# - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
# - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
config.disable_monkey_patching!
# Many RSpec users commonly either run the entire suite or an individual
# file, and it's useful to allow more verbose output when running an
# individual spec file.
if config.files_to_run.one?
# Use the documentation formatter for detailed output,
# unless a formatter has already been configured
# (e.g. via a command-line flag).
config.default_formatter = "doc"
end
# Print the 10 slowest examples and example groups at the
# end of the spec run, to help surface which specs are running
# particularly slow.
config.profile_examples = 10
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = :random
# Seed global randomization in this process using the `--seed` CLI option.
# Setting this allows you to use `--seed` to deterministically reproduce
# test failures related to randomization by passing the same `--seed` value
# as the one that triggered the failure.
Kernel.srand config.seed
=end
config.before :all, type: :feature do
unless Rails.application.routes.url_helpers.method_defined?(:matestack_components_test_path)
Rails.application.routes.append do
get '/matestack_components_test', to: 'matestack_components#matestack_components_test', as: :matestack_components_test
get '/matestack_transition_test', to: 'matestack_components#matestack_transition_test', as: :matestack_transition_test
get '/example', to: 'example#page'
get '/base_example', to: 'example#base'
end
Rails.application.reload_routes!
end
end
end
================================================
FILE: spec/dummy/Rakefile
================================================
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require_relative 'config/application'
Rails.application.load_tasks
================================================
FILE: spec/dummy/app/assets/config/manifest.js
================================================
//= link_tree ../images
//= link_tree ../videos
================================================
FILE: spec/dummy/app/assets/images/.keep
================================================
================================================
FILE: spec/dummy/app/channels/application_cable/channel.rb
================================================
module ApplicationCable
class Channel < ActionCable::Channel::Base
end
end
================================================
FILE: spec/dummy/app/channels/application_cable/connection.rb
================================================
module ApplicationCable
class Connection < ActionCable::Connection::Base
end
end
================================================
FILE: spec/dummy/app/controllers/application_controller.rb
================================================
class ApplicationController < ActionController::Base
end
================================================
FILE: spec/dummy/app/controllers/concerns/.keep
================================================
================================================
FILE: spec/dummy/app/controllers/demo_core_controller.rb
================================================
class DemoCoreController < ActionController::Base
include Matestack::Ui::Core::Helper
layout "application_core"
matestack_layout Demo::Core::Layout
def first
render Demo::Core::Pages::FirstPage
end
def second
render Demo::Core::Pages::SecondPage
end
end
================================================
FILE: spec/dummy/app/controllers/legacy_views/0_USED_IN_SPECS_DONT_TOUCH
================================================
================================================
FILE: spec/dummy/app/controllers/legacy_views/pages_controller.rb
================================================
# used in specs
class LegacyViews::PagesController < ApplicationController
include Matestack::Ui::Core::Helper
layout 'legacy_views'
def viewcontext_custom_component
end
end
================================================
FILE: spec/dummy/app/helpers/application_helper.rb
================================================
module ApplicationHelper
include Matestack::Ui::Core::Helper
include Matestack::Ui::Core::TagHelper
end
================================================
FILE: spec/dummy/app/javascript/channels/consumer.js
================================================
// Action Cable provides the framework to deal with WebSockets in Rails.
// You can generate new channels where WebSocket features live using the `rails generate channel` command.
import { createConsumer } from "@rails/actioncable"
export default createConsumer()
================================================
FILE: spec/dummy/app/javascript/channels/index.js
================================================
// Load all the channels within this directory and all subdirectories.
// Channel files must be named *_channel.js.
const channels = require.context('.', true, /_channel\.js$/)
channels.keys().forEach(channels)
================================================
FILE: spec/dummy/app/javascript/packs/application.js
================================================
/* eslint no-console:0 */
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
//
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
// layout file, like app/views/layouts/application.html.erb
require("@rails/ujs").start()
require("channels")
================================================
FILE: spec/dummy/app/javascript/packs/application_core.js
================================================
/* eslint no-console:0 */
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
//
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
// layout file, like app/views/layouts/application.html.erb
// require("@rails/ujs").start()
// require("channels")
================================================
FILE: spec/dummy/app/jobs/application_job.rb
================================================
class ApplicationJob < ActiveJob::Base
end
================================================
FILE: spec/dummy/app/mailers/application_mailer.rb
================================================
class ApplicationMailer < ActionMailer::Base
default from: 'from@example.com'
layout 'mailer'
end
================================================
FILE: spec/dummy/app/matestack/components/legacy_views/pages/0_USED_IN_SPECS_DONT_TOUCH
================================================
================================================
FILE: spec/dummy/app/matestack/components/legacy_views/pages/viewcontext.rb
================================================
# used in specs
class Components::LegacyViews::Pages::Viewcontext < Matestack::Ui::Component
def response
div id: "my-component" do
if view_context.view_renderer.instance_of?(ActionView::Renderer)
plain "has access to ActionView Context"
end
plain link_to "Test Link", "/some/page" # calling an ActionView Url Helper here
plain time_ago_in_words(3.minutes.from_now) # calling an ActionView Date Helper here
plain "root_path: #{root_path}" # calling a Path Helper here
end
end
end
================================================
FILE: spec/dummy/app/matestack/demo/core/components/static_component.rb
================================================
class Demo::Core::Components::StaticComponent < Matestack::Ui::Component
required :foo
def response
plain "A simple Static Component with given input foo: #{context.foo}"
end
end
================================================
FILE: spec/dummy/app/matestack/demo/core/layout.rb
================================================
class Demo::Core::Layout < Matestack::Ui::Layout
def response
h1 "Demo Core App"
paragraph do
plain "play around! --> spec/dummy/app/matestack/demo/core/app.rb"
end
nav do
a path: demo_core_first_page_path do
button "First Page"
end
a path: demo_core_second_page_path do
button "Second Page"
end
end
main do
yield
end
end
end
================================================
FILE: spec/dummy/app/matestack/demo/core/pages/first_page.rb
================================================
class Demo::Core::Pages::FirstPage < Matestack::Ui::Page
def response
h2 "First page"
paragraph do
plain "play around! --> spec/dummy/app/matestack/demo/core/pages/first_page.rb"
end
# you can call components on pages:
Demo::Core::Components::StaticComponent.call(foo: "bar")
end
end
================================================
FILE: spec/dummy/app/matestack/demo/core/pages/second_page.rb
================================================
class Demo::Core::Pages::SecondPage < Matestack::Ui::Page
def response
h2 "Second Page"
paragraph do
plain "play around! --> spec/dummy/app/matestack/demo/core/pages/second_page.rb"
end
# you can call components on pages:
Demo::Core::Components::StaticComponent.call(foo: "baz")
end
end
================================================
FILE: spec/dummy/app/models/0_USED_IN_SPECS_DONT_TOUCH
================================================
================================================
FILE: spec/dummy/app/models/application_record.rb
================================================
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end
================================================
FILE: spec/dummy/app/models/concerns/.keep
================================================
================================================
FILE: spec/dummy/app/models/dummy_child_model.rb
================================================
# used in specs
class DummyChildModel < ApplicationRecord
validates :title, presence: true, uniqueness: true
has_one_attached :file
has_many_attached :files
end
================================================
FILE: spec/dummy/app/models/dummy_model.rb
================================================
# used in specs
class DummyModel < ApplicationRecord
validates :title, presence: true, uniqueness: true
has_one_attached :file
has_many_attached :files
has_many :dummy_child_models, index_errors: true #https://bigbinary.com/blog/errors-can-be-indexed-with-nested-attrbutes-in-rails-5
accepts_nested_attributes_for :dummy_child_models, allow_destroy: true
end
================================================
FILE: spec/dummy/app/models/test_model.rb
================================================
# used in specs
class TestModel < ApplicationRecord
has_one_attached :file
end
================================================
FILE: spec/dummy/app/views/_some_partial.html.erb
================================================
<h1>This is some partial</h1>
<p><%= foo %></p>
================================================
FILE: spec/dummy/app/views/demo/0_USED_IN_SPECS_DONT_TOUCH
================================================
================================================
FILE: spec/dummy/app/views/demo/_header.html.erb
================================================
<header>
<h1>Rails Partial</h1>
<p><%= @title %></p>
</header>
================================================
FILE: spec/dummy/app/views/demo/header.html.erb
================================================
<header>
<h1>Rails View</h1>
<p><%= @title %></p>
</header>
================================================
FILE: spec/dummy/app/views/layouts/0_USED_IN_SPECS_DONT_TOUCH
================================================
================================================
FILE: spec/dummy/app/views/layouts/application.html.erb
================================================
<!DOCTYPE html>
<html>
<head>
<title>Dummy</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= javascript_pack_tag 'application' %>
</head>
<body>
<%= yield %>
<div id='from-rails-layout'></div>
</body>
</html>
================================================
FILE: spec/dummy/app/views/layouts/application_core.html.erb
================================================
<!DOCTYPE html>
<html>
<head>
<title>Core Demo</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= javascript_pack_tag 'application_core' %>
</head>
<body>
<%= yield %>
</body>
<div id='from-rails-core-layout'></div>
</html>
================================================
FILE: spec/dummy/app/views/layouts/legacy_views.erb
================================================
<!DOCTYPE html>
<html>
<head>
<title>Dummy</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= javascript_pack_tag 'application_vue_js' %>
</head>
<body>
<div id='matestack-ui'>
<nav>
<ul>Page 1</ul>
<ul>Page 2</ul>
</nav>
<div>
<%= yield %>
</div>
</div>
</body>
</html>
================================================
FILE: spec/dummy/app/views/legacy_views/pages/0_USED_IN_SPECS_DONT_TOUCH
================================================
================================================
FILE: spec/dummy/app/views/legacy_views/pages/viewcontext_custom_component.html.erb
================================================
<h1>Viewcontext Custom Component</h1>
<%= Components::LegacyViews::Pages::Viewcontext.() %>
================================================
FILE: spec/dummy/app/views/rails/0_USED_IN_SPECS_DONT_TOUCH
================================================
================================================
FILE: spec/dummy/app/views/rails/_some_partial.html.erb
================================================
<h2><%= name %></h2>
<% 5.times do |i| %>
<p><%= i %><p>
<% end %>
================================================
FILE: spec/dummy/app/views/rails/index.html.erb
================================================
<h1>Test</h1>
<% 100.times do %>
<div>
<div>
<div>
<div>
<div>
<div>
<b>Nested Content</b>
</div>
</div>
</div>
</div>
</div>
</div>
<% end %>
<%= render partial: 'rails/some_partial', collection: (1..100).to_a, as: :name %>
================================================
FILE: spec/dummy/app/views/some_view.html.erb
================================================
<h1>A view :D</h1>
<p><%= foo %></p>
================================================
FILE: spec/dummy/bin/bundle
================================================
#!/usr/bin/env ruby
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __dir__)
load Gem.bin_path('bundler', 'bundle')
================================================
FILE: spec/dummy/bin/rails
================================================
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../config/application', __dir__)
require_relative '../config/boot'
require 'rails/commands'
================================================
FILE: spec/dummy/bin/rake
================================================
#!/usr/bin/env ruby
require_relative '../config/boot'
require 'rake'
Rake.application.run
================================================
FILE: spec/dummy/bin/setup
================================================
#!/usr/bin/env ruby
require 'fileutils'
include FileUtils
# path to your application root.
APP_ROOT = File.expand_path('..', __dir__)
def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==")
end
chdir APP_ROOT do
# This script is a starting point to setup your application.
# Add necessary setup steps to this file.
puts '== Installing dependencies =='
system! 'gem install bundler --conservative'
system('bundle check') || system!('bundle install')
# Install JavaScript dependencies if using Yarn
# system('bin/yarn')
# puts "\n== Copying sample files =="
# unless File.exist?('config/database.yml')
# cp 'config/database.yml.sample', 'config/database.yml'
# end
puts "\n== Preparing database =="
system! 'bin/rails db:setup'
puts "\n== Removing old logs and tempfiles =="
system! 'bin/rails log:clear tmp:clear'
puts "\n== Restarting application server =="
system! 'bin/rails restart'
end
================================================
FILE: spec/dummy/bin/update
================================================
#!/usr/bin/env ruby
require 'fileutils'
include FileUtils
# path to your application root.
APP_ROOT = File.expand_path('..', __dir__)
def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==")
end
chdir APP_ROOT do
# This script is a way to update your development environment automatically.
# Add necessary update steps to this file.
puts '== Installing dependencies =='
system! 'gem install bundler --conservative'
system('bundle check') || system!('bundle install')
# Install JavaScript dependencies if using Yarn
# system('bin/yarn')
puts "\n== Updating database =="
system! 'bin/rails db:migrate'
puts "\n== Removing old logs and tempfiles =="
system! 'bin/rails log:clear tmp:clear'
puts "\n== Restarting application server =="
system! 'bin/rails restart'
end
================================================
FILE: spec/dummy/bin/webpack
================================================
#!/usr/bin/env ruby
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
ENV["NODE_ENV"] ||= "development"
require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../../Gemfile",
Pathname.new(__FILE__).realpath)
require "bundler/setup"
require "webpacker"
require "webpacker/webpack_runner"
APP_ROOT = File.expand_path("..", __dir__)
Dir.chdir(APP_ROOT) do
Webpacker::WebpackRunner.run(ARGV)
end
================================================
FILE: spec/dummy/bin/webpack-dev-server
================================================
#!/usr/bin/env ruby
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
ENV["NODE_ENV"] ||= "development"
require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../../Gemfile",
Pathname.new(__FILE__).realpath)
require "bundler/setup"
require "webpacker"
require "webpacker/dev_server_runner"
APP_ROOT = File.expand_path("..", __dir__)
Dir.chdir(APP_ROOT) do
Webpacker::DevServerRunner.run(ARGV)
end
================================================
FILE: spec/dummy/bin/yarn
================================================
#!/usr/bin/env ruby
APP_ROOT = File.expand_path('..', __dir__)
Dir.chdir(APP_ROOT) do
begin
exec "yarnpkg", *ARGV
rescue Errno::ENOENT
$stderr.puts "Yarn executable was not detected in the system."
$stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
exit 1
end
end
================================================
FILE: spec/dummy/config/application.5.2_rb
================================================
require_relative 'boot'
require 'rails/all'
Bundler.require(*Rails.groups)
require "matestack/ui/core"
module Dummy
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 5.2
# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading
# the framework and any gems in your application.
# config.eager_load_paths += %W( #{config.root}/app/matestack/registry )
end
end
================================================
FILE: spec/dummy/config/application.6.0_rb
================================================
require_relative 'boot'
require 'rails/all'
Bundler.require(*Rails.groups)
require "matestack/ui/core"
module Dummy
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.0
# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading
# the framework and any gems in your application.
# config.eager_load_paths += %W( #{config.root}/app/matestack/registry )
end
end
================================================
FILE: spec/dummy/config/application.6.1_rb
================================================
require_relative 'boot'
require 'rails/all'
Bundler.require(*Rails.groups)
require "matestack/ui/core"
module Dummy
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.1
# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading
# the framework and any gems in your application.
# config.eager_load_paths += %W( #{config.root}/app/matestack/registry )
end
end
================================================
FILE: spec/dummy/config/application.7.0_rb
================================================
require_relative 'boot'
require 'rails/all'
Bundler.require(*Rails.groups)
require "matestack/ui/core"
module Dummy
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 7.0
# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading
# the framework and any gems in your application.
# config.eager_load_paths += %W( #{config.root}/app/matestack/registry )
end
end
================================================
FILE: spec/dummy/config/application.rb
================================================
require_relative 'boot'
require 'rails/all'
Bundler.require(*Rails.groups)
require "matestack/ui/core"
module Dummy
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 7.0
# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading
# the framework and any gems in your application.
# config.eager_load_paths += %W( #{config.root}/app/matestack/reg
gitextract_mexlutwf/
├── .dockerignore
├── .gitattributes
├── .gitbook.yaml
├── .github/
│ ├── FUNDING.yml
│ ├── issue_template.md
│ ├── pull_request_template.md
│ └── workflows/
│ └── dockerpush.yml
├── .gitignore
├── .rspec
├── .ruby-version
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── Dockerfile.dev
├── Dockerfile.test
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── bin/
│ └── rails
├── ci/
│ ├── Dockerfile.test_5_2_ruby_2_6
│ ├── Dockerfile.test_6_0_ruby_2_6
│ ├── Dockerfile.test_6_1_ruby_2_7
│ ├── Dockerfile.test_6_1_ruby_3_0
│ ├── Dockerfile.test_7_0_ruby_3_0
│ ├── Gemfile.5.2
│ ├── Gemfile.6.0
│ ├── Gemfile.6.1
│ ├── Gemfile.7.0
│ ├── artifacts/
│ │ └── .keep
│ └── docker-compose.ci.yml
├── docker-compose.yml
├── docs/
│ ├── README.md
│ ├── SUMMARY.md
│ ├── components/
│ │ ├── api.md
│ │ ├── registry.md
│ │ ├── usage-in-isolation.md
│ │ ├── usage-on-matestack-layouts.md
│ │ ├── usage-on-matestack-pages.md
│ │ └── usage-on-rails-views.md
│ ├── getting-started/
│ │ ├── hello-world.md
│ │ └── installation-update.md
│ ├── html-rendering/
│ │ ├── html-rendering.md
│ │ ├── integrating-action-view-helpers.md
│ │ └── reusing-views-or-partials.md
│ ├── layouts/
│ │ ├── api.md
│ │ └── rails-controller-integration.md
│ ├── migrate-from-2.x-to-3.0.md
│ └── pages/
│ ├── api.md
│ └── rails-controller-integration.md
├── entrypoint.sh
├── lib/
│ └── matestack/
│ └── ui/
│ ├── component.rb
│ ├── core/
│ │ ├── base.rb
│ │ ├── component.rb
│ │ ├── context.rb
│ │ ├── helper.rb
│ │ ├── layout.rb
│ │ ├── page.rb
│ │ ├── properties.rb
│ │ ├── slots.rb
│ │ ├── tag_helper.rb
│ │ └── version.rb
│ ├── core.rb
│ ├── layout.rb
│ └── page.rb
├── matestack-ui-core.gemspec
├── results.txt
└── spec/
├── core_spec_helper.rb
├── dummy/
│ ├── Rakefile
│ ├── app/
│ │ ├── assets/
│ │ │ ├── config/
│ │ │ │ └── manifest.js
│ │ │ └── images/
│ │ │ └── .keep
│ │ ├── channels/
│ │ │ └── application_cable/
│ │ │ ├── channel.rb
│ │ │ └── connection.rb
│ │ ├── controllers/
│ │ │ ├── application_controller.rb
│ │ │ ├── concerns/
│ │ │ │ └── .keep
│ │ │ ├── demo_core_controller.rb
│ │ │ └── legacy_views/
│ │ │ ├── 0_USED_IN_SPECS_DONT_TOUCH
│ │ │ └── pages_controller.rb
│ │ ├── helpers/
│ │ │ └── application_helper.rb
│ │ ├── javascript/
│ │ │ ├── channels/
│ │ │ │ ├── consumer.js
│ │ │ │ └── index.js
│ │ │ └── packs/
│ │ │ ├── application.js
│ │ │ └── application_core.js
│ │ ├── jobs/
│ │ │ └── application_job.rb
│ │ ├── mailers/
│ │ │ └── application_mailer.rb
│ │ ├── matestack/
│ │ │ ├── components/
│ │ │ │ └── legacy_views/
│ │ │ │ └── pages/
│ │ │ │ ├── 0_USED_IN_SPECS_DONT_TOUCH
│ │ │ │ └── viewcontext.rb
│ │ │ └── demo/
│ │ │ └── core/
│ │ │ ├── components/
│ │ │ │ └── static_component.rb
│ │ │ ├── layout.rb
│ │ │ └── pages/
│ │ │ ├── first_page.rb
│ │ │ └── second_page.rb
│ │ ├── models/
│ │ │ ├── 0_USED_IN_SPECS_DONT_TOUCH
│ │ │ ├── application_record.rb
│ │ │ ├── concerns/
│ │ │ │ └── .keep
│ │ │ ├── dummy_child_model.rb
│ │ │ ├── dummy_model.rb
│ │ │ └── test_model.rb
│ │ └── views/
│ │ ├── _some_partial.html.erb
│ │ ├── demo/
│ │ │ ├── 0_USED_IN_SPECS_DONT_TOUCH
│ │ │ ├── _header.html.erb
│ │ │ └── header.html.erb
│ │ ├── layouts/
│ │ │ ├── 0_USED_IN_SPECS_DONT_TOUCH
│ │ │ ├── application.html.erb
│ │ │ ├── application_core.html.erb
│ │ │ └── legacy_views.erb
│ │ ├── legacy_views/
│ │ │ └── pages/
│ │ │ ├── 0_USED_IN_SPECS_DONT_TOUCH
│ │ │ └── viewcontext_custom_component.html.erb
│ │ ├── rails/
│ │ │ ├── 0_USED_IN_SPECS_DONT_TOUCH
│ │ │ ├── _some_partial.html.erb
│ │ │ └── index.html.erb
│ │ └── some_view.html.erb
│ ├── bin/
│ │ ├── bundle
│ │ ├── rails
│ │ ├── rake
│ │ ├── setup
│ │ ├── update
│ │ ├── webpack
│ │ ├── webpack-dev-server
│ │ └── yarn
│ ├── config/
│ │ ├── application.5.2_rb
│ │ ├── application.6.0_rb
│ │ ├── application.6.1_rb
│ │ ├── application.7.0_rb
│ │ ├── application.rb
│ │ ├── boot.rb
│ │ ├── cable.yml
│ │ ├── database.yml
│ │ ├── environment.rb
│ │ ├── environments/
│ │ │ ├── development.rb
│ │ │ ├── production.rb
│ │ │ └── test.rb
│ │ ├── initializers/
│ │ │ ├── application_controller_renderer.rb
│ │ │ ├── assets.rb
│ │ │ ├── backtrace_silencers.rb
│ │ │ ├── content_security_policy.rb
│ │ │ ├── cookies_serializer.rb
│ │ │ ├── filter_parameter_logging.rb
│ │ │ ├── inflections.rb
│ │ │ ├── matestack.rb
│ │ │ ├── mime_types.rb
│ │ │ ├── nested_attrs_error_index_patch.rb
│ │ │ └── wrap_parameters.rb
│ │ ├── locales/
│ │ │ └── en.yml
│ │ ├── puma.rb
│ │ ├── routes.rb
│ │ ├── spring.rb
│ │ ├── storage.yml
│ │ ├── webpack/
│ │ │ ├── development.js
│ │ │ ├── environment.js
│ │ │ ├── production.js
│ │ │ └── test.js
│ │ └── webpacker.yml
│ ├── config.ru
│ ├── db/
│ │ ├── migrate/
│ │ │ ├── 20190419174203_create_test_models.rb
│ │ │ ├── 20190427134012_create_dummy_models.rb
│ │ │ ├── 20190908153924_create_dummy_child_models.rb
│ │ │ ├── 20200427170812_create_active_storage_tables.active_storage.rb
│ │ │ ├── 20201222161321_add_boolean_value_to_test_models.rb
│ │ │ ├── 20210204135043_add_service_name_to_active_storage_blobs.active_storage.rb
│ │ │ └── 20210204135044_create_active_storage_variant_records.active_storage.rb
│ │ └── schema.rb
│ ├── lib/
│ │ └── assets/
│ │ └── .keep
│ ├── log/
│ │ └── .keep
│ ├── package.json
│ ├── postcss.config.js
│ └── public/
│ ├── 404.html
│ ├── 422.html
│ └── 500.html
├── rails_core_spec_helper.rb
├── spec_helper.rb
└── test/
└── core/
├── base/
│ ├── component/
│ │ ├── argument_spec.rb
│ │ ├── conditional_rendering_spec.rb
│ │ ├── core_namespaces_spec.rb
│ │ ├── custom_namespaces_spec.rb
│ │ ├── options_spec.rb
│ │ ├── partials_spec.rb
│ │ ├── prepare_spec.rb
│ │ ├── properties_spec.rb
│ │ ├── slots_spec.rb
│ │ ├── static_rendering_spec.rb
│ │ ├── url_params_access_spec.rb
│ │ ├── view_context_access_spec.rb
│ │ └── yield_spec.rb
│ ├── layout/
│ │ ├── layout_resolving_spec.rb
│ │ └── layout_spec.rb
│ └── page/
│ ├── controller_instance_access_spec.rb
│ ├── orchestrates_components_spec.rb
│ ├── partials_spec.rb
│ ├── prepare_spec.rb
│ ├── slots_spec.rb
│ ├── url_params_access_spec.rb
│ └── view_context_access_spec.rb
├── custom_component_spec.rb
├── html_rendering/
│ ├── action_view_integration.rb
│ ├── default_tags_spec.rb
│ └── link_spec.rb
├── rails_render_spec.rb
├── support/
│ ├── capybara.rb
│ ├── core_spec_utils.rb
│ ├── example_controller.rb
│ ├── layout.rb
│ ├── matestack_components_controller.rb
│ ├── matestack_wrapper_layout.rb
│ ├── matestack_wrapper_page.rb
│ ├── test_controller.rb
│ └── xss.rb
└── xss_spec.rb
SYMBOL INDEX (527 symbols across 72 files)
FILE: lib/matestack/ui/core.rb
type Matestack (line 4) | module Matestack
type Ui (line 5) | module Ui
type Core (line 6) | module Core
FILE: lib/matestack/ui/core/base.rb
type Matestack (line 3) | module Matestack
type Ui (line 4) | module Ui
type Core (line 5) | module Core
class Base (line 6) | class Base
method initialize (line 14) | def initialize(html_tag = nil, text = nil, options = {}, &block)
method render? (line 37) | def render?
method extract_options (line 42) | def extract_options(text, options)
method prepare (line 56) | def prepare
method create_children (line 63) | def create_children(&block)
method call (line 71) | def self.call(text = nil, options = {}, &block)
method children (line 75) | def children
method render_content (line 79) | def render_content
method params (line 95) | def params
method view_context (line 99) | def view_context
method method_missing (line 107) | def method_missing(name, *args, **kwargs, &block)
method to_str (line 118) | def to_str
FILE: lib/matestack/ui/core/component.rb
type Matestack (line 1) | module Matestack
type Ui (line 2) | module Ui
type Core (line 3) | module Core
class Component (line 4) | class Component < Base
FILE: lib/matestack/ui/core/context.rb
type Matestack (line 1) | module Matestack
type Ui (line 2) | module Ui
type Core (line 3) | module Core
class Context (line 4) | class Context < ActiveSupport::CurrentAttributes
FILE: lib/matestack/ui/core/helper.rb
type Matestack (line 1) | module Matestack
type Ui (line 2) | module Ui
type Core (line 3) | module Core
type Helper (line 4) | module Helper
function included (line 6) | def self.included(base)
type ClassMethods (line 10) | module ClassMethods
function inherited (line 11) | def inherited(subclass)
function matestack_layout (line 16) | def matestack_layout(layout = nil)
function render (line 21) | def render(*args)
function render_layout (line 73) | def render_layout(layout, page, options, root_layout)
function render_page (line 77) | def render_page(page, options, root_layout)
function render_component (line 81) | def render_component(layout, page, component_key, options)
function setup_context (line 86) | def setup_context
FILE: lib/matestack/ui/core/layout.rb
type Matestack (line 1) | module Matestack
type Ui (line 2) | module Ui
type Core (line 3) | module Core
class Layout (line 4) | class Layout < Base
method initialize (line 6) | def initialize(options = {})
method inherited (line 13) | def self.inherited(subclass)
method layout (line 18) | def self.layout(layout = nil)
FILE: lib/matestack/ui/core/page.rb
type Matestack (line 1) | module Matestack
type Ui (line 2) | module Ui
type Core (line 3) | module Core
class Page (line 4) | class Page < Base
method initialize (line 6) | def initialize(options = {})
FILE: lib/matestack/ui/core/properties.rb
type Matestack (line 1) | module Matestack
type Ui (line 2) | module Ui
type Core (line 3) | module Core
type Properties (line 4) | module Properties
function included (line 6) | def self.included(base)
type Initializer (line 11) | module Initializer
function initialize (line 12) | def initialize(html_tag = nil, text = nil, options = {}, &block)
type ClassMethods (line 20) | module ClassMethods
function required (line 23) | def required(*args)
function optional (line 28) | def optional(*args)
function required_property_keys (line 32) | def required_property_keys
function optional_property_keys (line 36) | def optional_property_keys
function inherited (line 40) | def inherited(subclass)
function context (line 47) | def context
function required_property_keys (line 52) | def required_property_keys
function optional_property_keys (line 56) | def optional_property_keys
function create_context (line 60) | def create_context
function create_context_for_properties (line 65) | def create_context_for_properties(properties, required: false)
function set_text (line 80) | def set_text
FILE: lib/matestack/ui/core/slots.rb
type Matestack (line 1) | module Matestack
type Ui (line 2) | module Ui
type Core (line 3) | module Core
type Slots (line 4) | module Slots
function slot (line 8) | def slot(key, *args)
FILE: lib/matestack/ui/core/tag_helper.rb
type Matestack (line 2) | module Matestack
type Ui (line 3) | module Ui
type Core (line 4) | module Core
type TagHelper (line 5) | module TagHelper
function plain (line 27) | def plain(text=nil, options=nil, &block)
function unescape (line 35) | def unescape(text)
function img (line 41) | def img(text = nil, options = {}, &block)
function a (line 49) | def a(text = nil, options = {}, &block)
function heading (line 60) | def heading(text = nil, options=nil, &block)
function rails_render (line 83) | def rails_render(options = {})
function detached (line 87) | def detached(text=nil, options=nil, &block)
function detached_to_s (line 93) | def detached_to_s(text=nil, options=nil, &block)
FILE: lib/matestack/ui/core/version.rb
type Matestack (line 1) | module Matestack
type Ui (line 2) | module Ui
type Core (line 3) | module Core
FILE: spec/dummy/app/channels/application_cable/channel.rb
type ApplicationCable (line 1) | module ApplicationCable
class Channel (line 2) | class Channel < ActionCable::Channel::Base
FILE: spec/dummy/app/channels/application_cable/connection.rb
type ApplicationCable (line 1) | module ApplicationCable
class Connection (line 2) | class Connection < ActionCable::Connection::Base
FILE: spec/dummy/app/controllers/application_controller.rb
class ApplicationController (line 1) | class ApplicationController < ActionController::Base
FILE: spec/dummy/app/controllers/demo_core_controller.rb
class DemoCoreController (line 1) | class DemoCoreController < ActionController::Base
method first (line 8) | def first
method second (line 12) | def second
FILE: spec/dummy/app/controllers/legacy_views/pages_controller.rb
class LegacyViews::PagesController (line 3) | class LegacyViews::PagesController < ApplicationController
method viewcontext_custom_component (line 8) | def viewcontext_custom_component
FILE: spec/dummy/app/helpers/application_helper.rb
type ApplicationHelper (line 1) | module ApplicationHelper
FILE: spec/dummy/app/jobs/application_job.rb
class ApplicationJob (line 1) | class ApplicationJob < ActiveJob::Base
FILE: spec/dummy/app/mailers/application_mailer.rb
class ApplicationMailer (line 1) | class ApplicationMailer < ActionMailer::Base
FILE: spec/dummy/app/matestack/components/legacy_views/pages/viewcontext.rb
class Components::LegacyViews::Pages::Viewcontext (line 3) | class Components::LegacyViews::Pages::Viewcontext < Matestack::Ui::Compo...
method response (line 5) | def response
FILE: spec/dummy/app/matestack/demo/core/components/static_component.rb
class Demo::Core::Components::StaticComponent (line 1) | class Demo::Core::Components::StaticComponent < Matestack::Ui::Component
method response (line 5) | def response
FILE: spec/dummy/app/matestack/demo/core/layout.rb
class Demo::Core::Layout (line 1) | class Demo::Core::Layout < Matestack::Ui::Layout
method response (line 3) | def response
FILE: spec/dummy/app/matestack/demo/core/pages/first_page.rb
class Demo::Core::Pages::FirstPage (line 1) | class Demo::Core::Pages::FirstPage < Matestack::Ui::Page
method response (line 3) | def response
FILE: spec/dummy/app/matestack/demo/core/pages/second_page.rb
class Demo::Core::Pages::SecondPage (line 1) | class Demo::Core::Pages::SecondPage < Matestack::Ui::Page
method response (line 3) | def response
FILE: spec/dummy/app/models/application_record.rb
class ApplicationRecord (line 1) | class ApplicationRecord < ActiveRecord::Base
FILE: spec/dummy/app/models/dummy_child_model.rb
class DummyChildModel (line 3) | class DummyChildModel < ApplicationRecord
FILE: spec/dummy/app/models/dummy_model.rb
class DummyModel (line 3) | class DummyModel < ApplicationRecord
FILE: spec/dummy/app/models/test_model.rb
class TestModel (line 3) | class TestModel < ApplicationRecord
FILE: spec/dummy/config/application.rb
type Dummy (line 8) | module Dummy
class Application (line 9) | class Application < Rails::Application
FILE: spec/dummy/config/initializers/nested_attrs_error_index_patch.rb
type ActiveRecord (line 4) | module ActiveRecord
type AutosaveAssociation (line 5) | module AutosaveAssociation
function validate_collection_association (line 6) | def validate_collection_association(reflection)
FILE: spec/dummy/db/migrate/20190419174203_create_test_models.rb
class CreateTestModels (line 1) | class CreateTestModels < ActiveRecord::Migration[5.2]
method change (line 2) | def change
FILE: spec/dummy/db/migrate/20190427134012_create_dummy_models.rb
class CreateDummyModels (line 1) | class CreateDummyModels < ActiveRecord::Migration[5.2]
method change (line 2) | def change
FILE: spec/dummy/db/migrate/20190908153924_create_dummy_child_models.rb
class CreateDummyChildModels (line 1) | class CreateDummyChildModels < ActiveRecord::Migration[5.2]
method change (line 2) | def change
FILE: spec/dummy/db/migrate/20200427170812_create_active_storage_tables.active_storage.rb
class CreateActiveStorageTables (line 2) | class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
method change (line 3) | def change
FILE: spec/dummy/db/migrate/20201222161321_add_boolean_value_to_test_models.rb
class AddBooleanValueToTestModels (line 1) | class AddBooleanValueToTestModels < ActiveRecord::Migration[5.2]
method change (line 2) | def change
FILE: spec/dummy/db/migrate/20210204135043_add_service_name_to_active_storage_blobs.active_storage.rb
class AddServiceNameToActiveStorageBlobs (line 3) | class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[6.0]
method up (line 4) | def up
method down (line 16) | def down
method up (line 22) | def up
method down (line 26) | def down
class AddServiceNameToActiveStorageBlobs (line 21) | class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[5.2]
method up (line 4) | def up
method down (line 16) | def down
method up (line 22) | def up
method down (line 26) | def down
FILE: spec/dummy/db/migrate/20210204135044_create_active_storage_variant_records.active_storage.rb
class CreateActiveStorageVariantRecords (line 3) | class CreateActiveStorageVariantRecords < ActiveRecord::Migration[6.0]
method change (line 4) | def change
method change (line 16) | def change
class CreateActiveStorageVariantRecords (line 15) | class CreateActiveStorageVariantRecords < ActiveRecord::Migration[5.2]
method change (line 4) | def change
method change (line 16) | def change
FILE: spec/test/core/base/component/argument_spec.rb
class ComponentTestController (line 8) | class ComponentTestController < ActionController::Base
method my_action (line 13) | def my_action
class SomeStaticComponent (line 32) | class SomeStaticComponent < Matestack::Ui::Component
method response (line 34) | def response
class ExamplePage (line 43) | class ExamplePage < Matestack::Ui::Page
method response (line 45) | def response
FILE: spec/test/core/base/component/conditional_rendering_spec.rb
class ComponentTestController (line 7) | class ComponentTestController < ActionController::Base
method my_action (line 11) | def my_action
class DefaultRenderingComponent (line 27) | class DefaultRenderingComponent < Matestack::Ui::Component
method response (line 28) | def response
class ExamplePage (line 37) | class ExamplePage < Matestack::Ui::Page
method response (line 38) | def response
method response (line 65) | def response
method response (line 92) | def response
class ConditionalRenderingComponent (line 50) | class ConditionalRenderingComponent < Matestack::Ui::Component
method response (line 51) | def response
method render? (line 57) | def render?
method response (line 78) | def response
method render? (line 84) | def render?
class ExamplePage (line 64) | class ExamplePage < Matestack::Ui::Page
method response (line 38) | def response
method response (line 65) | def response
method response (line 92) | def response
class ConditionalRenderingComponent (line 77) | class ConditionalRenderingComponent < Matestack::Ui::Component
method response (line 51) | def response
method render? (line 57) | def render?
method response (line 78) | def response
method render? (line 84) | def render?
class ExamplePage (line 91) | class ExamplePage < Matestack::Ui::Page
method response (line 38) | def response
method response (line 65) | def response
method response (line 92) | def response
FILE: spec/test/core/base/component/core_namespaces_spec.rb
type Components (line 8) | module Components end
type Pages (line 10) | module Pages end
type Matestack::Ui::Core (line 12) | module Matestack::Ui::Core end
class ComponentTestController (line 14) | class ComponentTestController < ActionController::Base
method my_action (line 19) | def my_action
type Matestack::Ui::Core::Component1 (line 39) | module Matestack::Ui::Core::Component1
class Matestack::Ui::Core::Component1::Component1 (line 43) | class Matestack::Ui::Core::Component1::Component1 < Matestack::Ui::Compo...
method response (line 44) | def response
class Matestack::Ui::Core::Component1::Component2 (line 54) | class Matestack::Ui::Core::Component1::Component2 < Matestack::Ui::Compo...
method response (line 55) | def response
class Matestack::Ui::Core::Component1::ThirdComponent (line 65) | class Matestack::Ui::Core::Component1::ThirdComponent < Matestack::Ui::C...
method response (line 66) | def response
class Pages::ExamplePage (line 75) | class Pages::ExamplePage < Matestack::Ui::Page
method response (line 76) | def response
FILE: spec/test/core/base/component/custom_namespaces_spec.rb
type Components (line 8) | module Components end
type Pages (line 10) | module Pages end
type Matestack::Ui::Core (line 12) | module Matestack::Ui::Core end
class ComponentTestController (line 14) | class ComponentTestController < ActionController::Base
method my_action (line 19) | def my_action
type Components (line 40) | module Components end
class Components::Component1 (line 43) | class Components::Component1 < Matestack::Ui::Component
method response (line 45) | def response
type Components::Namespace1 (line 55) | module Components::Namespace1 end
class Components::Namespace1::Component1 (line 58) | class Components::Namespace1::Component1 < Matestack::Ui::Component
method response (line 60) | def response
class Components::MyCamelcasedClassNameComponent (line 71) | class Components::MyCamelcasedClassNameComponent < Matestack::Ui::Component
method response (line 73) | def response
class Pages::ExamplePage (line 82) | class Pages::ExamplePage < Matestack::Ui::Page
method response (line 84) | def response
FILE: spec/test/core/base/component/options_spec.rb
class ComponentTestController (line 8) | class ComponentTestController < ActionController::Base
method my_action (line 13) | def my_action
class SomeStaticComponent (line 32) | class SomeStaticComponent < Matestack::Ui::Component
method response (line 34) | def response
class ExamplePage (line 43) | class ExamplePage < Matestack::Ui::Page
method response (line 45) | def response
method response (line 77) | def response
class SpecialComponent (line 61) | class SpecialComponent < Matestack::Ui::Component
method response (line 66) | def response
class ExamplePage (line 75) | class ExamplePage < Matestack::Ui::Page
method response (line 45) | def response
method response (line 77) | def response
FILE: spec/test/core/base/component/partials_spec.rb
class ComponentTestController (line 7) | class ComponentTestController < ActionController::Base
method my_action (line 11) | def my_action
class SomeStaticComponent (line 27) | class SomeStaticComponent < Matestack::Ui::Component
method response (line 28) | def response
method my_partial (line 34) | def my_partial text
method response (line 65) | def response
class ExamplePage (line 41) | class ExamplePage < Matestack::Ui::Page
method response (line 43) | def response
method response (line 75) | def response
type MySharedPartials (line 56) | module MySharedPartials
function my_partial (line 57) | def my_partial text
class SomeStaticComponent (line 62) | class SomeStaticComponent < Matestack::Ui::Component
method response (line 28) | def response
method my_partial (line 34) | def my_partial text
method response (line 65) | def response
class ExamplePage (line 74) | class ExamplePage < Matestack::Ui::Page
method response (line 43) | def response
method response (line 75) | def response
FILE: spec/test/core/base/component/prepare_spec.rb
class ComponentTestController (line 8) | class ComponentTestController < ActionController::Base
method my_action (line 13) | def my_action
class SomeStaticComponent (line 32) | class SomeStaticComponent < Matestack::Ui::Component
method prepare (line 34) | def prepare
method response (line 38) | def response
class ExamplePage (line 47) | class ExamplePage < Matestack::Ui::Page
method response (line 49) | def response
FILE: spec/test/core/base/component/properties_spec.rb
class PropertyComponent (line 7) | class PropertyComponent < Matestack::Ui::Component
method response (line 13) | def response
class ExamplePage (line 27) | class ExamplePage < Matestack::Ui::Page
method response (line 28) | def response
method response (line 39) | def response
method response (line 52) | def response
method response (line 66) | def response
method response (line 94) | def response
method response (line 120) | def response
method some_slot (line 124) | def some_slot
method other_slot (line 128) | def other_slot
class ExamplePage (line 38) | class ExamplePage < Matestack::Ui::Page
method response (line 28) | def response
method response (line 39) | def response
method response (line 52) | def response
method response (line 66) | def response
method response (line 94) | def response
method response (line 120) | def response
method some_slot (line 124) | def some_slot
method other_slot (line 128) | def other_slot
class ExamplePage (line 51) | class ExamplePage < Matestack::Ui::Page
method response (line 28) | def response
method response (line 39) | def response
method response (line 52) | def response
method response (line 66) | def response
method response (line 94) | def response
method response (line 120) | def response
method some_slot (line 124) | def some_slot
method other_slot (line 128) | def other_slot
class ExamplePage (line 65) | class ExamplePage < Matestack::Ui::Page
method response (line 28) | def response
method response (line 39) | def response
method response (line 52) | def response
method response (line 66) | def response
method response (line 94) | def response
method response (line 120) | def response
method some_slot (line 124) | def some_slot
method other_slot (line 128) | def other_slot
class SetupComponent (line 80) | class SetupComponent < Matestack::Ui::Component
method prepare (line 82) | def prepare
method response (line 86) | def response
class ExamplePage (line 93) | class ExamplePage < Matestack::Ui::Page
method response (line 28) | def response
method response (line 39) | def response
method response (line 52) | def response
method response (line 66) | def response
method response (line 94) | def response
method response (line 120) | def response
method some_slot (line 124) | def some_slot
method other_slot (line 128) | def other_slot
class SlotComponent (line 109) | class SlotComponent < Matestack::Ui::Component
method response (line 110) | def response
class ExamplePage (line 119) | class ExamplePage < Matestack::Ui::Page
method response (line 28) | def response
method response (line 39) | def response
method response (line 52) | def response
method response (line 66) | def response
method response (line 94) | def response
method response (line 120) | def response
method some_slot (line 124) | def some_slot
method other_slot (line 128) | def other_slot
class Component (line 145) | class Component < Matestack::Ui::Component
method response (line 147) | def response
method response (line 168) | def response
class AnotherComponent (line 150) | class AnotherComponent < Component
class Component (line 166) | class Component < Matestack::Ui::Component
method response (line 147) | def response
method response (line 168) | def response
class AnotherComponent (line 171) | class AnotherComponent < Component
class Component2 (line 187) | class Component2 < Matestack::Ui::Component
class AnotherComponent2 (line 190) | class AnotherComponent2 < Component2
class AliasPropertyComponent (line 202) | class AliasPropertyComponent < Matestack::Ui::Component
method response (line 204) | def response
class AnotherAliasPropertyComponent (line 207) | class AnotherAliasPropertyComponent < Matestack::Ui::Component
method response (line 209) | def response
class OptionalAliasPropertyComponent (line 224) | class OptionalAliasPropertyComponent < Matestack::Ui::Component
method response (line 226) | def response
class AnotherOptionalAliasPropertyComponent (line 229) | class AnotherOptionalAliasPropertyComponent < Matestack::Ui::Component
method response (line 231) | def response
FILE: spec/test/core/base/component/slots_spec.rb
class ComponentTestController (line 8) | class ComponentTestController < ActionController::Base
method my_action (line 11) | def my_action
class SomeStaticComponent (line 30) | class SomeStaticComponent < Matestack::Ui::Component
method response (line 32) | def response
method response (line 93) | def response
method my_slot_from_component (line 103) | def my_slot_from_component
class ExamplePage (line 43) | class ExamplePage < Matestack::Ui::Page
method response (line 45) | def response
method my_simple_slot (line 52) | def my_simple_slot
method my_second_simple_slot (line 58) | def my_second_simple_slot
method response (line 128) | def response
method my_slot_from_page (line 135) | def my_slot_from_page
class SomeStaticComponent (line 91) | class SomeStaticComponent < Matestack::Ui::Component
method response (line 32) | def response
method response (line 93) | def response
method my_slot_from_component (line 103) | def my_slot_from_component
class OtherComponent (line 112) | class OtherComponent < Matestack::Ui::Component
method response (line 114) | def response
class ExamplePage (line 126) | class ExamplePage < Matestack::Ui::Page
method response (line 45) | def response
method my_simple_slot (line 52) | def my_simple_slot
method my_second_simple_slot (line 58) | def my_second_simple_slot
method response (line 128) | def response
method my_slot_from_page (line 135) | def my_slot_from_page
FILE: spec/test/core/base/component/static_rendering_spec.rb
class ComponentTestController (line 7) | class ComponentTestController < ActionController::Base
method my_action (line 11) | def my_action
class SomeStaticComponent (line 27) | class SomeStaticComponent < Matestack::Ui::Component
method response (line 28) | def response
class ExamplePage (line 37) | class ExamplePage < Matestack::Ui::Page
method response (line 38) | def response
FILE: spec/test/core/base/component/url_params_access_spec.rb
class ComponentTestController (line 8) | class ComponentTestController < ActionController::Base
method my_action (line 13) | def my_action
class SomeStaticComponent (line 32) | class SomeStaticComponent < Matestack::Ui::Component
method response (line 34) | def response
class ExamplePage (line 45) | class ExamplePage < Matestack::Ui::Page
method response (line 47) | def response
FILE: spec/test/core/base/component/view_context_access_spec.rb
class SomeLayout (line 8) | class SomeLayout < Matestack::Ui::Layout
method response (line 9) | def response
class ComponentTestController (line 14) | class ComponentTestController < ActionController::Base
method my_action (line 18) | def my_action
class SomeStaticComponent (line 34) | class SomeStaticComponent < Matestack::Ui::Component
method response (line 35) | def response
class ExamplePage (line 49) | class ExamplePage < Matestack::Ui::Page
method response (line 50) | def response
FILE: spec/test/core/base/component/yield_spec.rb
class ComponentTestController (line 8) | class ComponentTestController < ActionController::Base
method my_action (line 11) | def my_action
class SomeStaticComponent (line 28) | class SomeStaticComponent < Matestack::Ui::Component
method response (line 29) | def response
class ExamplePage (line 38) | class ExamplePage < Matestack::Ui::Page
method response (line 40) | def response
FILE: spec/test/core/base/layout/layout_resolving_spec.rb
class ExamplePage (line 26) | class ExamplePage < Matestack::Ui::Page
method response (line 28) | def response
method response (line 74) | def response
method response (line 124) | def response
class RenderTestAController (line 36) | class RenderTestAController < ActionController::Base
method example (line 41) | def example
type ExampleApp (line 54) | module ExampleApp
class ExampleApp::Layout (line 57) | class ExampleApp::Layout < Matestack::Ui::Layout
method response (line 58) | def response
method response (line 108) | def response
class ExampleApp::SomeOtherExampleLayout (line 65) | class ExampleApp::SomeOtherExampleLayout < Matestack::Ui::Layout
method response (line 66) | def response
method response (line 116) | def response
class ExamplePage (line 73) | class ExamplePage < Matestack::Ui::Page
method response (line 28) | def response
method response (line 74) | def response
method response (line 124) | def response
class RenderTestBController (line 82) | class RenderTestBController < ActionController::Base
method example (line 86) | def example
method second_example (line 90) | def second_example
type ExampleApp (line 104) | module ExampleApp
class ExampleApp::Layout (line 107) | class ExampleApp::Layout < Matestack::Ui::Layout
method response (line 58) | def response
method response (line 108) | def response
class ExampleApp::SomeOtherExampleLayout (line 115) | class ExampleApp::SomeOtherExampleLayout < Matestack::Ui::Layout
method response (line 66) | def response
method response (line 116) | def response
class ExamplePage (line 123) | class ExamplePage < Matestack::Ui::Page
method response (line 28) | def response
method response (line 74) | def response
method response (line 124) | def response
class RenderTestCController (line 132) | class RenderTestCController < ActionController::Base
method example (line 137) | def example
method second_example (line 141) | def second_example
type Layouts (line 158) | module Layouts end
class Layouts::ExampleLayout (line 159) | class Layouts::ExampleLayout < Matestack::Ui::Layout
method response (line 160) | def response
class Layouts::SomeOtherExampleLayout (line 167) | class Layouts::SomeOtherExampleLayout < Matestack::Ui::Layout
method response (line 168) | def response
type Pages (line 175) | module Pages end
type Pages::ExampleLayout (line 176) | module Pages::ExampleLayout end
type Pages::SomeOtherExampleLayout (line 177) | module Pages::SomeOtherExampleLayout end
class Pages::ExampleLayout::ExamplePage (line 179) | class Pages::ExampleLayout::ExamplePage < Matestack::Ui::Page
method response (line 180) | def response
class Pages::SomeOtherExampleLayout::ExamplePage (line 187) | class Pages::SomeOtherExampleLayout::ExamplePage < Matestack::Ui::Page
method response (line 188) | def response
class RenderTestEController (line 197) | class RenderTestEController < ActionController::Base
method example (line 201) | def example
method second_example (line 205) | def second_example
FILE: spec/test/core/base/layout/layout_spec.rb
type ExampleApp (line 17) | module ExampleApp
class ExampleApp::App (line 20) | class ExampleApp::App < Matestack::Ui::Layout
method response (line 21) | def response
method response (line 78) | def response
type ExampleApp::Pages (line 31) | module ExampleApp::Pages
class ExampleApp::Pages::ExamplePage (line 34) | class ExampleApp::Pages::ExamplePage < Matestack::Ui::Page
method response (line 35) | def response
method response (line 92) | def response
class ExampleApp::Pages::SecondExamplePage (line 42) | class ExampleApp::Pages::SecondExamplePage < Matestack::Ui::Page
method response (line 43) | def response
class ExampleAppPagesController (line 50) | class ExampleAppPagesController < ExampleController
method page1 (line 54) | def page1
method page2 (line 58) | def page2
method page1 (line 104) | def page1
type ExampleApp (line 72) | module ExampleApp
class ExampleApp::App (line 75) | class ExampleApp::App < Matestack::Ui::Layout
method response (line 21) | def response
method response (line 78) | def response
type ExampleApp::Pages (line 88) | module ExampleApp::Pages
class ExampleApp::Pages::ExamplePage (line 91) | class ExampleApp::Pages::ExamplePage < Matestack::Ui::Page
method response (line 35) | def response
method response (line 92) | def response
class ExampleAppPagesController (line 99) | class ExampleAppPagesController < ExampleController
method page1 (line 54) | def page1
method page2 (line 58) | def page2
method page1 (line 104) | def page1
FILE: spec/test/core/base/page/controller_instance_access_spec.rb
class ExamplePage (line 16) | class ExamplePage < Matestack::Ui::Page
method response (line 18) | def response
class PageTestController (line 26) | class PageTestController < ActionController::Base
method my_action (line 29) | def my_action
FILE: spec/test/core/base/page/orchestrates_components_spec.rb
class PageTestController (line 7) | class PageTestController < ActionController::Base
method my_action (line 12) | def my_action
class ExamplePage (line 28) | class ExamplePage < Matestack::Ui::Page
method response (line 30) | def response
FILE: spec/test/core/base/page/partials_spec.rb
class PageTestController (line 7) | class PageTestController < ActionController::Base
method my_action (line 12) | def my_action
class ExamplePage (line 28) | class ExamplePage < Matestack::Ui::Page
method response (line 30) | def response
method my_simple_partial (line 38) | def my_simple_partial
method my_partial_with_param (line 44) | def my_partial_with_param some_param
method my_partial_with_partial (line 50) | def my_partial_with_partial
method response (line 103) | def response
method my_simple_partial (line 111) | def my_simple_partial
method my_partial_with_partial (line 117) | def my_partial_with_partial
type MySharedPartials (line 89) | module MySharedPartials
function my_partial_with_param (line 91) | def my_partial_with_param some_param
class ExamplePage (line 99) | class ExamplePage < Matestack::Ui::Page
method response (line 30) | def response
method my_simple_partial (line 38) | def my_simple_partial
method my_partial_with_param (line 44) | def my_partial_with_param some_param
method my_partial_with_partial (line 50) | def my_partial_with_partial
method response (line 103) | def response
method my_simple_partial (line 111) | def my_simple_partial
method my_partial_with_partial (line 117) | def my_partial_with_partial
FILE: spec/test/core/base/page/slots_spec.rb
class PageTestController (line 7) | class PageTestController < ActionController::Base
method my_action (line 12) | def my_action
class SlotTestComponent (line 29) | class SlotTestComponent < Matestack::Ui::Component
method prepare (line 31) | def prepare
method response (line 35) | def response
class ExamplePage (line 45) | class ExamplePage < Matestack::Ui::Page
method response (line 47) | def response
method my_simple_slot (line 54) | def my_simple_slot
method my_second_simple_slot (line 60) | def my_second_simple_slot
FILE: spec/test/core/base/page/url_params_access_spec.rb
class PageTestController (line 7) | class PageTestController < ActionController::Base
method my_action (line 12) | def my_action
class ExamplePage (line 28) | class ExamplePage < Matestack::Ui::Page
method response (line 30) | def response
FILE: spec/test/core/base/page/view_context_access_spec.rb
class PageTestController (line 7) | class PageTestController < ActionController::Base
method my_action (line 12) | def my_action
class ExamplePage (line 29) | class ExamplePage < Matestack::Ui::Page
method response (line 31) | def response
FILE: spec/test/core/custom_component_spec.rb
type Components (line 7) | module Components end
type Pages (line 9) | module Pages end
type Matestack::Ui::Core (line 11) | module Matestack::Ui::Core end
class SomeLayout (line 13) | class SomeLayout < Matestack::Ui::Layout
method response (line 14) | def response
class ComponentTestController (line 19) | class ComponentTestController < ActionController::Base
method my_action (line 23) | def my_action
type Components (line 35) | module Components end
class Components::CrazyComponent (line 37) | class Components::CrazyComponent < Matestack::Ui::Component
method response (line 38) | def response
class ExamplePage (line 47) | class ExamplePage < Matestack::Ui::Page
method response (line 48) | def response
FILE: spec/test/core/html_rendering/action_view_integration.rb
class ExamplePage (line 7) | class ExamplePage < Matestack::Ui::Page
method response (line 8) | def response
method response (line 32) | def response
method response (line 69) | def response
method some_partial (line 89) | def some_partial
method some_partial_rendering_view_helpers (line 95) | def some_partial_rendering_view_helpers f
class ExamplePage (line 31) | class ExamplePage < Matestack::Ui::Page
method response (line 8) | def response
method response (line 32) | def response
method response (line 69) | def response
method some_partial (line 89) | def some_partial
method some_partial_rendering_view_helpers (line 95) | def some_partial_rendering_view_helpers f
class ExamplePage (line 68) | class ExamplePage < Matestack::Ui::Page
method response (line 8) | def response
method response (line 32) | def response
method response (line 69) | def response
method some_partial (line 89) | def some_partial
method some_partial_rendering_view_helpers (line 95) | def some_partial_rendering_view_helpers f
FILE: spec/test/core/html_rendering/default_tags_spec.rb
class ExamplePage (line 9) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 19) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 29) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 47) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 70) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 97) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 107) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 117) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 127) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 141) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 155) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 171) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 191) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 219) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 231) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 253) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 317) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 330) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 344) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 360) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 372) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 384) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 400) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 412) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 427) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
class ExamplePage (line 458) | class ExamplePage < Matestack::Ui::Page
method response (line 10) | def response
method response (line 20) | def response
method response (line 30) | def response
method response (line 48) | def response
method response (line 71) | def response
method response (line 98) | def response
method response (line 108) | def response
method response (line 118) | def response
method response (line 128) | def response
method response (line 142) | def response
method response (line 156) | def response
method response (line 172) | def response
method response (line 192) | def response
method response (line 220) | def response
method response (line 232) | def response
method response (line 254) | def response
method response (line 318) | def response
method response (line 331) | def response
method response (line 345) | def response
method response (line 361) | def response
method response (line 373) | def response
method response (line 385) | def response
method response (line 401) | def response
method response (line 413) | def response
method response (line 428) | def response
method response (line 459) | def response
FILE: spec/test/core/html_rendering/link_spec.rb
class ExamplePage (line 7) | class ExamplePage < Matestack::Ui::Page
method response (line 8) | def response
method response (line 27) | def response
method response (line 48) | def response
method response (line 74) | def response
method response (line 100) | def response
method response (line 119) | def response
method set_app_class (line 150) | def set_app_class
method response (line 164) | def response
method set_app_class (line 176) | def set_app_class
method response (line 201) | def response
method set_app_class (line 210) | def set_app_class
class ExamplePage (line 26) | class ExamplePage < Matestack::Ui::Page
method response (line 8) | def response
method response (line 27) | def response
method response (line 48) | def response
method response (line 74) | def response
method response (line 100) | def response
method response (line 119) | def response
method set_app_class (line 150) | def set_app_class
method response (line 164) | def response
method set_app_class (line 176) | def set_app_class
method response (line 201) | def response
method set_app_class (line 210) | def set_app_class
class ExamplePage (line 47) | class ExamplePage < Matestack::Ui::Page
method response (line 8) | def response
method response (line 27) | def response
method response (line 48) | def response
method response (line 74) | def response
method response (line 100) | def response
method response (line 119) | def response
method set_app_class (line 150) | def set_app_class
method response (line 164) | def response
method set_app_class (line 176) | def set_app_class
method response (line 201) | def response
method set_app_class (line 210) | def set_app_class
class ExamplePage (line 73) | class ExamplePage < Matestack::Ui::Page
method response (line 8) | def response
method response (line 27) | def response
method response (line 48) | def response
method response (line 74) | def response
method response (line 100) | def response
method response (line 119) | def response
method set_app_class (line 150) | def set_app_class
method response (line 164) | def response
method set_app_class (line 176) | def set_app_class
method response (line 201) | def response
method set_app_class (line 210) | def set_app_class
class ExamplePage (line 99) | class ExamplePage < Matestack::Ui::Page
method response (line 8) | def response
method response (line 27) | def response
method response (line 48) | def response
method response (line 74) | def response
method response (line 100) | def response
method response (line 119) | def response
method set_app_class (line 150) | def set_app_class
method response (line 164) | def response
method set_app_class (line 176) | def set_app_class
method response (line 201) | def response
method set_app_class (line 210) | def set_app_class
class ExamplePage (line 118) | class ExamplePage < Matestack::Ui::Page
method response (line 8) | def response
method response (line 27) | def response
method response (line 48) | def response
method response (line 74) | def response
method response (line 100) | def response
method response (line 119) | def response
method set_app_class (line 150) | def set_app_class
method response (line 164) | def response
method set_app_class (line 176) | def set_app_class
method response (line 201) | def response
method set_app_class (line 210) | def set_app_class
class ExamplePage (line 146) | class ExamplePage < Matestack::Ui::Page
method response (line 8) | def response
method response (line 27) | def response
method response (line 48) | def response
method response (line 74) | def response
method response (line 100) | def response
method response (line 119) | def response
method set_app_class (line 150) | def set_app_class
method response (line 164) | def response
method set_app_class (line 176) | def set_app_class
method response (line 201) | def response
method set_app_class (line 210) | def set_app_class
class MyTestApp (line 157) | class MyTestApp < Matestack::Ui::Layout
method response (line 158) | def response
method response (line 195) | def response
class ExamplePage (line 163) | class ExamplePage < Matestack::Ui::Page
method response (line 8) | def response
method response (line 27) | def response
method response (line 48) | def response
method response (line 74) | def response
method response (line 100) | def response
method response (line 119) | def response
method set_app_class (line 150) | def set_app_class
method response (line 164) | def response
method set_app_class (line 176) | def set_app_class
method response (line 201) | def response
method set_app_class (line 210) | def set_app_class
class MyTestApp (line 194) | class MyTestApp < Matestack::Ui::Layout
method response (line 158) | def response
method response (line 195) | def response
class ExamplePage (line 200) | class ExamplePage < Matestack::Ui::Page
method response (line 8) | def response
method response (line 27) | def response
method response (line 48) | def response
method response (line 74) | def response
method response (line 100) | def response
method response (line 119) | def response
method set_app_class (line 150) | def set_app_class
method response (line 164) | def response
method set_app_class (line 176) | def set_app_class
method response (line 201) | def response
method set_app_class (line 210) | def set_app_class
FILE: spec/test/core/rails_render_spec.rb
class ExampleController (line 7) | class ExampleController < ApplicationController
method page (line 8) | def page
method page (line 16) | def page
class ExampleController (line 15) | class ExampleController < ApplicationController
method page (line 8) | def page
method page (line 16) | def page
class ExamplePage (line 22) | class ExamplePage < Matestack::Ui::Page
method response (line 23) | def response
FILE: spec/test/core/support/core_spec_utils.rb
type CoreSpecUtils (line 1) | module CoreSpecUtils
function stripped (line 3) | def stripped(html_string)
function path_exists? (line 11) | def path_exists?(path_as_symbol)
function register_component (line 18) | def register_component(dsl_method, component_class)
function register_self_as (line 26) | def register_self_as(dsl_method)
function matestack_render (line 30) | def matestack_render(reset_app: true, page: MatestackWrapperPage, &block)
function matestack_layout (line 36) | def matestack_layout(&block)
function reset_matestack_layout (line 40) | def reset_matestack_layout
FILE: spec/test/core/support/example_controller.rb
class ExampleController (line 3) | class ExampleController < ApplicationController
method page (line 9) | def page
method base (line 13) | def base
FILE: spec/test/core/support/layout.rb
class Layout (line 3) | class Layout < Matestack::Ui::Layout
method response (line 5) | def response
FILE: spec/test/core/support/matestack_components_controller.rb
class MatestackComponentsController (line 4) | class MatestackComponentsController < ApplicationController
method matestack_components_test (line 9) | def matestack_components_test
method matestack_transition_test (line 13) | def matestack_transition_test
FILE: spec/test/core/support/matestack_wrapper_layout.rb
class MatestackWrapperLayout (line 1) | class MatestackWrapperLayout < Matestack::Ui::Layout
method response (line 2) | def response
method app_body (line 7) | def app_body
FILE: spec/test/core/support/matestack_wrapper_page.rb
class MatestackWrapperPage (line 1) | class MatestackWrapperPage < Matestack::Ui::Page
method response (line 2) | def response
FILE: spec/test/core/support/test_controller.rb
class TestController (line 1) | class TestController < ActionController::Base
method check_params (line 4) | def check_params
method expect_params (line 8) | def expect_params(params)
FILE: spec/test/core/support/xss.rb
type XSS (line 1) | module XSS
FILE: spec/test/core/xss_spec.rb
function expect_alert (line 52) | def expect_alert(alert)
Condensed preview — 206 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (338K chars).
[
{
"path": ".dockerignore",
"chars": 439,
"preview": "node_modules/\nspec/dummy/db/*.sqlite3\nspec/dummy/db/*.sqlite3-journal\nspec/dummy/log/*.log\nspec/dummy/node_modules/\nspec"
},
{
"path": ".gitattributes",
"chars": 30,
"preview": "docs/* linguist-documentation\n"
},
{
"path": ".gitbook.yaml",
"chars": 68,
"preview": "root: ./docs/\n\nstructure:\n readme: README.md\n summary: SUMMARY.md\n"
},
{
"path": ".github/FUNDING.yml",
"chars": 67,
"preview": "# These are supported funding model platforms\n\ngithub: [matestack]\n"
},
{
"path": ".github/issue_template.md",
"chars": 935,
"preview": "<!-- This is a template only, remove/add sections below as appropriate (e.g. for a new feature, there might be no 'curre"
},
{
"path": ".github/pull_request_template.md",
"chars": 333,
"preview": "**Note:** If you submit a feature or bugfix PR, pick **develop** as target branch (and delete this line afterwards).\n\n##"
},
{
"path": ".github/workflows/dockerpush.yml",
"chars": 2126,
"preview": "name: specs\n\non:\n push:\n paths-ignore:\n - 'docs/**'\n - 'README.md'\n - 'CHANGELOG.md'\n\njobs:\n test_7_"
},
{
"path": ".gitignore",
"chars": 293,
"preview": ".bundle/\nlog/*.log\nnode_modules/\ncoverage/\nspec/dummy/db/*.sqlite3\nspec/dummy/db/*.sqlite3-journal\nspec/dummy/log/*.log\n"
},
{
"path": ".rspec",
"chars": 22,
"preview": "--require spec_helper\n"
},
{
"path": ".ruby-version",
"chars": 6,
"preview": "2.6.5\n"
},
{
"path": "CHANGELOG.md",
"chars": 45832,
"preview": "# Changelog\n\n## v3.0.1 Release - 2022-04-29\n\n### Bugfixes\n\n- fixing layout resolving issue when using the `turbo-rails` "
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 3351,
"preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
},
{
"path": "Dockerfile.dev",
"chars": 313,
"preview": "FROM ruby:3.0-alpine3.12\n\nRUN gem install bundler:2.1.4\n\nRUN apk update --no-cache && \\\n apk add build-base postgresq"
},
{
"path": "Dockerfile.test",
"chars": 825,
"preview": "FROM ruby:3.0-alpine3.12\n\nRUN gem install bundler:2.1.4\n\nRUN apk update --no-cache && \\\n apk add build-base postgresq"
},
{
"path": "Gemfile",
"chars": 1034,
"preview": "source 'https://rubygems.org'\ngit_source(:github) { |repo| \"https://github.com/#{repo}.git\" }\n\n# Declare your gem's depe"
},
{
"path": "LICENSE",
"chars": 1051,
"preview": "Copyright (c) MateLab GmbH\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this softwar"
},
{
"path": "README.md",
"chars": 9309,
"preview": "[](https://github.com/matestack/matest"
},
{
"path": "Rakefile",
"chars": 1377,
"preview": "begin\n require 'bundler/setup'\nrescue LoadError\n puts 'You must `gem install bundler` and `bundle install` to run rake"
},
{
"path": "bin/rails",
"chars": 563,
"preview": "#!/usr/bin/env ruby\n# This command will automatically be run when you run \"rails\" with Rails gems\n# installed from the r"
},
{
"path": "ci/Dockerfile.test_5_2_ruby_2_6",
"chars": 1215,
"preview": "FROM ruby:2.6-alpine3.12\n\nRUN gem install bundler:2.1.4\n\nRUN apk update --no-cache && \\\n apk add build-base postgresq"
},
{
"path": "ci/Dockerfile.test_6_0_ruby_2_6",
"chars": 1215,
"preview": "FROM ruby:2.6-alpine3.12\n\nRUN gem install bundler:2.1.4\n\nRUN apk update --no-cache && \\\n apk add build-base postgresq"
},
{
"path": "ci/Dockerfile.test_6_1_ruby_2_7",
"chars": 1215,
"preview": "FROM ruby:2.7-alpine3.12\n\nRUN gem install bundler:2.1.4\n\nRUN apk update --no-cache && \\\n apk add build-base postgresq"
},
{
"path": "ci/Dockerfile.test_6_1_ruby_3_0",
"chars": 1215,
"preview": "FROM ruby:3.0-alpine3.12\n\nRUN gem install bundler:2.1.4\n\nRUN apk update --no-cache && \\\n apk add build-base postgresq"
},
{
"path": "ci/Dockerfile.test_7_0_ruby_3_0",
"chars": 1215,
"preview": "FROM ruby:3.0-alpine3.12\n\nRUN gem install bundler:2.1.4\n\nRUN apk update --no-cache && \\\n apk add build-base postgresq"
},
{
"path": "ci/Gemfile.5.2",
"chars": 1027,
"preview": "source 'https://rubygems.org'\ngit_source(:github) { |repo| \"https://github.com/#{repo}.git\" }\n\n# Declare your gem's depe"
},
{
"path": "ci/Gemfile.6.0",
"chars": 1027,
"preview": "source 'https://rubygems.org'\ngit_source(:github) { |repo| \"https://github.com/#{repo}.git\" }\n\n# Declare your gem's depe"
},
{
"path": "ci/Gemfile.6.1",
"chars": 1027,
"preview": "source 'https://rubygems.org'\ngit_source(:github) { |repo| \"https://github.com/#{repo}.git\" }\n\n# Declare your gem's depe"
},
{
"path": "ci/Gemfile.7.0",
"chars": 1027,
"preview": "source 'https://rubygems.org'\ngit_source(:github) { |repo| \"https://github.com/#{repo}.git\" }\n\n# Declare your gem's depe"
},
{
"path": "ci/artifacts/.keep",
"chars": 0,
"preview": ""
},
{
"path": "ci/docker-compose.ci.yml",
"chars": 2896,
"preview": "version: '3'\nservices:\n\n test_5_2_ruby_2_6:\n build:\n context: ../\n dockerfile: ./ci/Dockerfile.test_5_2_ru"
},
{
"path": "docker-compose.yml",
"chars": 1518,
"preview": "version: '3'\nservices:\n\n dummy:\n build:\n context: .\n dockerfile: ./Dockerfile.dev\n ports:\n - \"3000"
},
{
"path": "docs/README.md",
"chars": 11367,
"preview": "---\ndescription: >-\n Matestack Ui Core - Boost your productivity & easily create component based\n web UIs in pure Ruby"
},
{
"path": "docs/SUMMARY.md",
"chars": 1049,
"preview": "# Table of contents\n\n* [Welcome](README.md)\n* [Migrating from 2.x to 3.0](migrate-from-2.x-to-3.0.md)\n\n## Getting starte"
},
{
"path": "docs/components/api.md",
"chars": 14847,
"preview": "# API\n\n## Response\n\nUse the `response` method to define the UI of the component by using Matestack's HTML rendering or c"
},
{
"path": "docs/components/registry.md",
"chars": 1504,
"preview": "# Registry\n\nBy default, components can be called directly like `Components::Card.call(title: \"foo\", body: \"bar\")` which "
},
{
"path": "docs/components/usage-in-isolation.md",
"chars": 22,
"preview": "# Usage in Isolation\n\n"
},
{
"path": "docs/components/usage-on-matestack-layouts.md",
"chars": 30,
"preview": "# Usage on Matestack Layouts\n\n"
},
{
"path": "docs/components/usage-on-matestack-pages.md",
"chars": 28,
"preview": "# Usage on Matestack Pages\n\n"
},
{
"path": "docs/components/usage-on-rails-views.md",
"chars": 1034,
"preview": "# Components on Rails views\n\nIf you already have plenty of Rails views \\(ERB, Haml or Slim\\) and want to start creating "
},
{
"path": "docs/getting-started/hello-world.md",
"chars": 20,
"preview": "# Hello World\n\nWIP!\n"
},
{
"path": "docs/getting-started/installation-update.md",
"chars": 1175,
"preview": "# Installation & Update\n\n## Installation\n\nAdd 'matestack-ui-core' to your Gemfile\n\n```ruby\ngem 'matestack-ui-core'\n```\n\n"
},
{
"path": "docs/html-rendering/html-rendering.md",
"chars": 4656,
"preview": "# Basic Rendering Mechanism\n\nMatestack’s rendering mechanism takes care of converting Ruby into HTML:\n\n```ruby\ndiv class"
},
{
"path": "docs/html-rendering/integrating-action-view-helpers.md",
"chars": 2122,
"preview": "# Integrating Action View Helpers\n\nUsing Rails view helpers ([https://api.rubyonrails.org/classes/ActionView/Helpers.htm"
},
{
"path": "docs/html-rendering/reusing-views-or-partials.md",
"chars": 1880,
"preview": "# Integrating Rails Views or Partials\n\nMatestack `rails_render` component offers the possibility to render a view or par"
},
{
"path": "docs/layouts/api.md",
"chars": 3105,
"preview": "# API\n\nA layout class defines a layout within its `response` method and is suppose to yield the content of a page.\n\n## R"
},
{
"path": "docs/layouts/rails-controller-integration.md",
"chars": 11069,
"preview": "# Rails Controller Integration\n\nJust like a Rails layout would yield a Rails view, a Matestack layout yields a Matestack"
},
{
"path": "docs/migrate-from-2.x-to-3.0.md",
"chars": 3120,
"preview": "# Migrating from 2.x to 3.0\n\n## Core/VueJs repo and gem split\n\n* `matestack-ui-core` previously contained logic for\n * "
},
{
"path": "docs/pages/api.md",
"chars": 3268,
"preview": "# Page API\n\n## Response\n\nUse the `response` method to define the UI of the page by using Matestack's HTML rendering or c"
},
{
"path": "docs/pages/rails-controller-integration.md",
"chars": 1060,
"preview": "# Rails Controller Integration\n\nPages are used as Rails view substitutes and therefore called in a Rails controller acti"
},
{
"path": "entrypoint.sh",
"chars": 261,
"preview": "#!/bin/bash\nset -e\n\nif [[ ! -e /app/Gemfile.lock ]]; then\n bundle install\nfi\n\n# Remove a potentially pre-existing ser"
},
{
"path": "lib/matestack/ui/component.rb",
"chars": 57,
"preview": "Matestack::Ui::Component = Matestack::Ui::Core::Component"
},
{
"path": "lib/matestack/ui/core/base.rb",
"chars": 4588,
"preview": "require_relative 'tag_helper'\n\nmodule Matestack\n module Ui\n module Core\n class Base\n include ActionView:"
},
{
"path": "lib/matestack/ui/core/component.rb",
"chars": 101,
"preview": "module Matestack\n module Ui\n module Core\n class Component < Base\n end\n end\n end\nend"
},
{
"path": "lib/matestack/ui/core/context.rb",
"chars": 344,
"preview": "module Matestack\n module Ui\n module Core\n class Context < ActiveSupport::CurrentAttributes\n\n attribute :"
},
{
"path": "lib/matestack/ui/core/helper.rb",
"chars": 3587,
"preview": "module Matestack\n module Ui\n module Core\n module Helper\n\n def self.included(base)\n base.extend "
},
{
"path": "lib/matestack/ui/core/layout.rb",
"chars": 532,
"preview": "module Matestack\n module Ui\n module Core\n class Layout < Base\n\n def initialize(options = {})\n @"
},
{
"path": "lib/matestack/ui/core/page.rb",
"chars": 183,
"preview": "module Matestack\n module Ui\n module Core\n class Page < Base\n\n def initialize(options = {})\n sup"
},
{
"path": "lib/matestack/ui/core/properties.rb",
"chars": 3579,
"preview": "module Matestack\n module Ui\n module Core\n module Properties\n\n def self.included(base)\n base.ext"
},
{
"path": "lib/matestack/ui/core/slots.rb",
"chars": 197,
"preview": "module Matestack\n module Ui\n module Core\n module Slots\n\n attr_accessor :slots\n\n def slot(key, *ar"
},
{
"path": "lib/matestack/ui/core/tag_helper.rb",
"chars": 3877,
"preview": "require_relative 'slots'\nmodule Matestack\n module Ui\n module Core\n module TagHelper\n extend Gem::Depreca"
},
{
"path": "lib/matestack/ui/core/version.rb",
"chars": 87,
"preview": "module Matestack\n module Ui\n module Core\n VERSION = '3.0.1'\n end\n end\nend\n"
},
{
"path": "lib/matestack/ui/core.rb",
"chars": 490,
"preview": "base_path = 'matestack/ui/core'\nrequire \"#{base_path}/version\"\n\nmodule Matestack\n module Ui\n module Core\n\n end\n "
},
{
"path": "lib/matestack/ui/layout.rb",
"chars": 52,
"preview": "Matestack::Ui::Layout = Matestack::Ui::Core::Layout\n"
},
{
"path": "lib/matestack/ui/page.rb",
"chars": 48,
"preview": "Matestack::Ui::Page = Matestack::Ui::Core::Page\n"
},
{
"path": "matestack-ui-core.gemspec",
"chars": 1004,
"preview": "$:.push File.expand_path(\"lib\", __dir__)\n\n# Maintain your gem's version:\nrequire \"matestack/ui/core/version\"\n\n# Describe"
},
{
"path": "results.txt",
"chars": 447,
"preview": "Capybara starting Puma...\n* Version 4.3.5 , codename: Mysterious Traveller\n* Min threads: 0, max threads: 4\n* Listening "
},
{
"path": "spec/core_spec_helper.rb",
"chars": 6088,
"preview": "# This file was generated by the `rails generate rspec:install` command. Conventionally, all\n# specs live under a `spec`"
},
{
"path": "spec/dummy/Rakefile",
"chars": 227,
"preview": "# Add your own tasks in files placed in lib/tasks ending in .rake,\n# for example lib/tasks/capistrano.rake, and they wil"
},
{
"path": "spec/dummy/app/assets/config/manifest.js",
"chars": 48,
"preview": "//= link_tree ../images\n//= link_tree ../videos\n"
},
{
"path": "spec/dummy/app/assets/images/.keep",
"chars": 0,
"preview": ""
},
{
"path": "spec/dummy/app/channels/application_cable/channel.rb",
"chars": 79,
"preview": "module ApplicationCable\n class Channel < ActionCable::Channel::Base\n end\nend\n"
},
{
"path": "spec/dummy/app/channels/application_cable/connection.rb",
"chars": 85,
"preview": "module ApplicationCable\n class Connection < ActionCable::Connection::Base\n end\nend\n"
},
{
"path": "spec/dummy/app/controllers/application_controller.rb",
"chars": 57,
"preview": "class ApplicationController < ActionController::Base\nend\n"
},
{
"path": "spec/dummy/app/controllers/concerns/.keep",
"chars": 0,
"preview": ""
},
{
"path": "spec/dummy/app/controllers/demo_core_controller.rb",
"chars": 281,
"preview": "class DemoCoreController < ActionController::Base\n include Matestack::Ui::Core::Helper\n\n layout \"application_core\"\n\n "
},
{
"path": "spec/dummy/app/controllers/legacy_views/0_USED_IN_SPECS_DONT_TOUCH",
"chars": 0,
"preview": ""
},
{
"path": "spec/dummy/app/controllers/legacy_views/pages_controller.rb",
"chars": 186,
"preview": "# used in specs\n\nclass LegacyViews::PagesController < ApplicationController\n include Matestack::Ui::Core::Helper\n\n lay"
},
{
"path": "spec/dummy/app/helpers/application_helper.rb",
"chars": 108,
"preview": "module ApplicationHelper\n include Matestack::Ui::Core::Helper\n include Matestack::Ui::Core::TagHelper\nend\n"
},
{
"path": "spec/dummy/app/javascript/channels/consumer.js",
"chars": 266,
"preview": "// Action Cable provides the framework to deal with WebSockets in Rails.\n// You can generate new channels where WebSocke"
},
{
"path": "spec/dummy/app/javascript/channels/index.js",
"chars": 212,
"preview": "// Load all the channels within this directory and all subdirectories.\n// Channel files must be named *_channel.js.\n\ncon"
},
{
"path": "spec/dummy/app/javascript/packs/application.js",
"chars": 523,
"preview": "/* eslint no-console:0 */\n// This file is automatically compiled by Webpack, along with any other files\n// present in th"
},
{
"path": "spec/dummy/app/javascript/packs/application_core.js",
"chars": 529,
"preview": "/* eslint no-console:0 */\n// This file is automatically compiled by Webpack, along with any other files\n// present in th"
},
{
"path": "spec/dummy/app/jobs/application_job.rb",
"chars": 43,
"preview": "class ApplicationJob < ActiveJob::Base\nend\n"
},
{
"path": "spec/dummy/app/mailers/application_mailer.rb",
"chars": 102,
"preview": "class ApplicationMailer < ActionMailer::Base\n default from: 'from@example.com'\n layout 'mailer'\nend\n"
},
{
"path": "spec/dummy/app/matestack/components/legacy_views/pages/0_USED_IN_SPECS_DONT_TOUCH",
"chars": 0,
"preview": ""
},
{
"path": "spec/dummy/app/matestack/components/legacy_views/pages/viewcontext.rb",
"chars": 533,
"preview": "# used in specs\n\nclass Components::LegacyViews::Pages::Viewcontext < Matestack::Ui::Component\n\n def response\n div id"
},
{
"path": "spec/dummy/app/matestack/demo/core/components/static_component.rb",
"chars": 192,
"preview": "class Demo::Core::Components::StaticComponent < Matestack::Ui::Component\n\n required :foo\n\n def response\n plain \"A s"
},
{
"path": "spec/dummy/app/matestack/demo/core/layout.rb",
"chars": 415,
"preview": "class Demo::Core::Layout < Matestack::Ui::Layout\n\n def response\n h1 \"Demo Core App\"\n\n paragraph do\n plain \"p"
},
{
"path": "spec/dummy/app/matestack/demo/core/pages/first_page.rb",
"chars": 318,
"preview": "class Demo::Core::Pages::FirstPage < Matestack::Ui::Page\n\n def response\n h2 \"First page\"\n\n paragraph do\n pla"
},
{
"path": "spec/dummy/app/matestack/demo/core/pages/second_page.rb",
"chars": 321,
"preview": "class Demo::Core::Pages::SecondPage < Matestack::Ui::Page\n\n def response\n h2 \"Second Page\"\n\n paragraph do\n p"
},
{
"path": "spec/dummy/app/models/0_USED_IN_SPECS_DONT_TOUCH",
"chars": 0,
"preview": ""
},
{
"path": "spec/dummy/app/models/application_record.rb",
"chars": 78,
"preview": "class ApplicationRecord < ActiveRecord::Base\n self.abstract_class = true\nend\n"
},
{
"path": "spec/dummy/app/models/concerns/.keep",
"chars": 0,
"preview": ""
},
{
"path": "spec/dummy/app/models/dummy_child_model.rb",
"chars": 171,
"preview": "# used in specs\n\nclass DummyChildModel < ApplicationRecord\n\n validates :title, presence: true, uniqueness: true\n\n has_"
},
{
"path": "spec/dummy/app/models/dummy_model.rb",
"chars": 373,
"preview": "# used in specs\n\nclass DummyModel < ApplicationRecord\n\n validates :title, presence: true, uniqueness: true\n\n has_one_a"
},
{
"path": "spec/dummy/app/models/test_model.rb",
"chars": 84,
"preview": "# used in specs\n\nclass TestModel < ApplicationRecord\n\n has_one_attached :file\n\nend\n"
},
{
"path": "spec/dummy/app/views/_some_partial.html.erb",
"chars": 47,
"preview": "<h1>This is some partial</h1>\n<p><%= foo %></p>"
},
{
"path": "spec/dummy/app/views/demo/0_USED_IN_SPECS_DONT_TOUCH",
"chars": 0,
"preview": ""
},
{
"path": "spec/dummy/app/views/demo/_header.html.erb",
"chars": 66,
"preview": "<header>\n <h1>Rails Partial</h1>\n <p><%= @title %></p>\n</header>"
},
{
"path": "spec/dummy/app/views/demo/header.html.erb",
"chars": 63,
"preview": "<header>\n <h1>Rails View</h1>\n <p><%= @title %></p>\n</header>"
},
{
"path": "spec/dummy/app/views/layouts/0_USED_IN_SPECS_DONT_TOUCH",
"chars": 0,
"preview": ""
},
{
"path": "spec/dummy/app/views/layouts/application.html.erb",
"chars": 247,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <title>Dummy</title>\n <%= csrf_meta_tags %>\n <%= csp_meta_tag %>\n\n <%= java"
},
{
"path": "spec/dummy/app/views/layouts/application_core.html.erb",
"chars": 260,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <title>Core Demo</title>\n <%= csrf_meta_tags %>\n <%= csp_meta_tag %>\n\n <%= "
},
{
"path": "spec/dummy/app/views/layouts/legacy_views.erb",
"chars": 356,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <title>Dummy</title>\n <%= csrf_meta_tags %>\n <%= csp_meta_tag %>\n\n <%= java"
},
{
"path": "spec/dummy/app/views/legacy_views/pages/0_USED_IN_SPECS_DONT_TOUCH",
"chars": 0,
"preview": ""
},
{
"path": "spec/dummy/app/views/legacy_views/pages/viewcontext_custom_component.html.erb",
"chars": 92,
"preview": "<h1>Viewcontext Custom Component</h1>\n<%= Components::LegacyViews::Pages::Viewcontext.() %>\n"
},
{
"path": "spec/dummy/app/views/rails/0_USED_IN_SPECS_DONT_TOUCH",
"chars": 0,
"preview": ""
},
{
"path": "spec/dummy/app/views/rails/_some_partial.html.erb",
"chars": 68,
"preview": "<h2><%= name %></h2>\n<% 5.times do |i| %>\n <p><%= i %><p>\n<% end %>"
},
{
"path": "spec/dummy/app/views/rails/index.html.erb",
"chars": 322,
"preview": "<h1>Test</h1>\n<% 100.times do %>\n <div>\n <div>\n <div>\n <div>\n <div>\n <div>\n "
},
{
"path": "spec/dummy/app/views/some_view.html.erb",
"chars": 36,
"preview": "<h1>A view :D</h1>\n<p><%= foo %></p>"
},
{
"path": "spec/dummy/bin/bundle",
"chars": 134,
"preview": "#!/usr/bin/env ruby\nENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __dir__)\nload Gem.bin_path('bundle"
},
{
"path": "spec/dummy/bin/rails",
"chars": 141,
"preview": "#!/usr/bin/env ruby\nAPP_PATH = File.expand_path('../config/application', __dir__)\nrequire_relative '../config/boot'\nrequ"
},
{
"path": "spec/dummy/bin/rake",
"chars": 90,
"preview": "#!/usr/bin/env ruby\nrequire_relative '../config/boot'\nrequire 'rake'\nRake.application.run\n"
},
{
"path": "spec/dummy/bin/setup",
"chars": 957,
"preview": "#!/usr/bin/env ruby\nrequire 'fileutils'\ninclude FileUtils\n\n# path to your application root.\nAPP_ROOT = File.expand_path("
},
{
"path": "spec/dummy/bin/update",
"chars": 819,
"preview": "#!/usr/bin/env ruby\nrequire 'fileutils'\ninclude FileUtils\n\n# path to your application root.\nAPP_ROOT = File.expand_path("
},
{
"path": "spec/dummy/bin/webpack",
"chars": 420,
"preview": "#!/usr/bin/env ruby\n\nENV[\"RAILS_ENV\"] ||= ENV[\"RACK_ENV\"] || \"development\"\nENV[\"NODE_ENV\"] ||= \"development\"\n\nrequire \""
},
{
"path": "spec/dummy/bin/webpack-dev-server",
"chars": 425,
"preview": "#!/usr/bin/env ruby\n\nENV[\"RAILS_ENV\"] ||= ENV[\"RACK_ENV\"] || \"development\"\nENV[\"NODE_ENV\"] ||= \"development\"\n\nrequire \""
},
{
"path": "spec/dummy/bin/yarn",
"chars": 303,
"preview": "#!/usr/bin/env ruby\nAPP_ROOT = File.expand_path('..', __dir__)\nDir.chdir(APP_ROOT) do\n begin\n exec \"yarnpkg\", *ARGV\n"
},
{
"path": "spec/dummy/config/application.5.2_rb",
"chars": 647,
"preview": "require_relative 'boot'\n\nrequire 'rails/all'\n\nBundler.require(*Rails.groups)\nrequire \"matestack/ui/core\"\n\nmodule Dummy\n "
},
{
"path": "spec/dummy/config/application.6.0_rb",
"chars": 647,
"preview": "require_relative 'boot'\n\nrequire 'rails/all'\n\nBundler.require(*Rails.groups)\nrequire \"matestack/ui/core\"\n\nmodule Dummy\n "
},
{
"path": "spec/dummy/config/application.6.1_rb",
"chars": 647,
"preview": "require_relative 'boot'\n\nrequire 'rails/all'\n\nBundler.require(*Rails.groups)\nrequire \"matestack/ui/core\"\n\nmodule Dummy\n "
},
{
"path": "spec/dummy/config/application.7.0_rb",
"chars": 647,
"preview": "require_relative 'boot'\n\nrequire 'rails/all'\n\nBundler.require(*Rails.groups)\nrequire \"matestack/ui/core\"\n\nmodule Dummy\n "
},
{
"path": "spec/dummy/config/application.rb",
"chars": 647,
"preview": "require_relative 'boot'\n\nrequire 'rails/all'\n\nBundler.require(*Rails.groups)\nrequire \"matestack/ui/core\"\n\nmodule Dummy\n "
},
{
"path": "spec/dummy/config/boot.rb",
"chars": 233,
"preview": "# Set up gems listed in the Gemfile.\nENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__)\n\nrequire 'b"
},
{
"path": "spec/dummy/config/cable.yml",
"chars": 187,
"preview": "development:\n adapter: async\n\ntest:\n adapter: async\n\nproduction:\n adapter: redis\n url: <%= ENV.fetch(\"REDIS_URL\") { "
},
{
"path": "spec/dummy/config/database.yml",
"chars": 482,
"preview": "default: &default\n adapter: postgresql\n encoding: unicode\n host: postgres\n username: <%= ENV.fetch(\"POSTGRES_USER\") "
},
{
"path": "spec/dummy/config/environment.rb",
"chars": 128,
"preview": "# Load the Rails application.\nrequire_relative 'application'\n\n# Initialize the Rails application.\nRails.application.init"
},
{
"path": "spec/dummy/config/environments/development.rb",
"chars": 2326,
"preview": "Rails.application.configure do\n # Verifies that versions and hashed value of the package contents in the project's pack"
},
{
"path": "spec/dummy/config/environments/production.rb",
"chars": 4083,
"preview": "Rails.application.configure do\n # Verifies that versions and hashed value of the package contents in the project's pack"
},
{
"path": "spec/dummy/config/environments/test.rb",
"chars": 1873,
"preview": "Rails.application.configure do\n # Settings specified here will take precedence over those in config/application.rb.\n\n "
},
{
"path": "spec/dummy/config/initializers/application_controller_renderer.rb",
"chars": 216,
"preview": "# Be sure to restart your server when you modify this file.\n\n# ActiveSupport::Reloader.to_prepare do\n# ApplicationCont"
},
{
"path": "spec/dummy/config/initializers/assets.rb",
"chars": 762,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Version of your assets, change this if you want to expire"
},
{
"path": "spec/dummy/config/initializers/backtrace_silencers.rb",
"chars": 404,
"preview": "# Be sure to restart your server when you modify this file.\n\n# You can add backtrace silencers for libraries that you're"
},
{
"path": "spec/dummy/config/initializers/content_security_policy.rb",
"chars": 1092,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Define an application-wide content security policy\n# For "
},
{
"path": "spec/dummy/config/initializers/cookies_serializer.rb",
"chars": 244,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Specify a serializer for the signed and encrypted cookie "
},
{
"path": "spec/dummy/config/initializers/filter_parameter_logging.rb",
"chars": 194,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Configure sensitive parameters which will be filtered fro"
},
{
"path": "spec/dummy/config/initializers/inflections.rb",
"chars": 647,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Add new inflection rules using the following format. Infl"
},
{
"path": "spec/dummy/config/initializers/matestack.rb",
"chars": 90,
"preview": "# Matestack::Ui::Core::Component::Registry.register_component(:my_card, Components::Card)\n"
},
{
"path": "spec/dummy/config/initializers/mime_types.rb",
"chars": 156,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Add new mime types for use in respond_to blocks:\n# Mime::"
},
{
"path": "spec/dummy/config/initializers/nested_attrs_error_index_patch.rb",
"chars": 681,
"preview": "# Support propper mapping of errors on existing nested models in nested forms\n# https://github.com/rails/rails/issues/24"
},
{
"path": "spec/dummy/config/initializers/wrap_parameters.rb",
"chars": 485,
"preview": "# Be sure to restart your server when you modify this file.\n\n# This file contains settings for ActionController::ParamsW"
},
{
"path": "spec/dummy/config/locales/en.yml",
"chars": 848,
"preview": "# Files in the config/locales directory are used for internationalization\n# and are automatically loaded by Rails. If yo"
},
{
"path": "spec/dummy/config/puma.rb",
"chars": 1397,
"preview": "# Puma can serve each request in a thread from an internal thread pool.\n# The `threads` method setting takes two numbers"
},
{
"path": "spec/dummy/config/routes.rb",
"chars": 256,
"preview": "Rails.application.routes.draw do\n\n root to: 'demo_core#first'\n\n scope :demo do\n scope :core do\n get :first, to"
},
{
"path": "spec/dummy/config/spring.rb",
"chars": 111,
"preview": "%w[\n .ruby-version\n .rbenv-vars\n tmp/restart.txt\n tmp/caching-dev.txt\n].each { |path| Spring.watch(path) }\n"
},
{
"path": "spec/dummy/config/storage.yml",
"chars": 1093,
"preview": "test:\n service: Disk\n root: <%= Rails.root.join(\"tmp/storage\") %>\n\nlocal:\n service: Disk\n root: <%= Rails.root.join("
},
{
"path": "spec/dummy/config/webpack/development.js",
"chars": 155,
"preview": "process.env.NODE_ENV = process.env.NODE_ENV || 'development'\n\nconst environment = require('./environment')\n\nmodule.expor"
},
{
"path": "spec/dummy/config/webpack/environment.js",
"chars": 82,
"preview": "const { environment } = require('@rails/webpacker')\n\nmodule.exports = environment\n"
},
{
"path": "spec/dummy/config/webpack/production.js",
"chars": 154,
"preview": "process.env.NODE_ENV = process.env.NODE_ENV || 'production'\n\nconst environment = require('./environment')\n\nmodule.export"
},
{
"path": "spec/dummy/config/webpack/test.js",
"chars": 155,
"preview": "process.env.NODE_ENV = process.env.NODE_ENV || 'development'\n\nconst environment = require('./environment')\n\nmodule.expor"
},
{
"path": "spec/dummy/config/webpacker.yml",
"chars": 1426,
"preview": "# Note: You must restart bin/webpack-dev-server for changes to take effect\n\ndefault: &default\n source_path: app/javascr"
},
{
"path": "spec/dummy/config.ru",
"chars": 130,
"preview": "# This file is used by Rack-based servers to start the application.\n\nrequire_relative 'config/environment'\n\nrun Rails.ap"
},
{
"path": "spec/dummy/db/migrate/20190419174203_create_test_models.rb",
"chars": 262,
"preview": "class CreateTestModels < ActiveRecord::Migration[5.2]\n def change\n create_table :test_models do |t|\n t.string :"
},
{
"path": "spec/dummy/db/migrate/20190427134012_create_dummy_models.rb",
"chars": 264,
"preview": "class CreateDummyModels < ActiveRecord::Migration[5.2]\n def change\n create_table :dummy_models do |t|\n t.string"
},
{
"path": "spec/dummy/db/migrate/20190908153924_create_dummy_child_models.rb",
"chars": 346,
"preview": "class CreateDummyChildModels < ActiveRecord::Migration[5.2]\n def change\n create_table :dummy_child_models do |t|\n "
},
{
"path": "spec/dummy/db/migrate/20200427170812_create_active_storage_tables.active_storage.rb",
"chars": 968,
"preview": "# This migration comes from active_storage (originally 20170806125915)\nclass CreateActiveStorageTables < ActiveRecord::M"
},
{
"path": "spec/dummy/db/migrate/20201222161321_add_boolean_value_to_test_models.rb",
"chars": 147,
"preview": "class AddBooleanValueToTestModels < ActiveRecord::Migration[5.2]\n def change\n add_column :test_models, :some_boolean"
},
{
"path": "spec/dummy/db/migrate/20210204135043_add_service_name_to_active_storage_blobs.active_storage.rb",
"chars": 826,
"preview": "# This migration comes from active_storage (originally 20190112182829)\nif Rails::VERSION::MAJOR >= 6 && Rails::VERSION::"
},
{
"path": "spec/dummy/db/migrate/20210204135044_create_active_storage_variant_records.active_storage.rb",
"chars": 702,
"preview": "# This migration comes from active_storage (originally 20191206030411)\nif Rails::VERSION::MAJOR >= 6 && Rails::VERSION::"
},
{
"path": "spec/dummy/db/schema.rb",
"chars": 3214,
"preview": "# This file is auto-generated from the current state of the database. Instead\n# of editing this file, please use the mig"
},
{
"path": "spec/dummy/lib/assets/.keep",
"chars": 0,
"preview": ""
},
{
"path": "spec/dummy/log/.keep",
"chars": 0,
"preview": ""
},
{
"path": "spec/dummy/package.json",
"chars": 359,
"preview": "{\n \"name\": \"dummy\",\n \"private\": true,\n \"dependencies\": {\n \"@babel/preset-env\": \"^7.16.7\",\n \"@hotwired/turbo-rai"
},
{
"path": "spec/dummy/postcss.config.js",
"chars": 224,
"preview": "module.exports = {\n plugins: [\n require('postcss-import'),\n require('postcss-flexbugs-fixes'),\n require('postc"
},
{
"path": "spec/dummy/public/404.html",
"chars": 1722,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>The page you were looking for doesn't exist (404)</title>\n <meta name=\"viewport\""
},
{
"path": "spec/dummy/public/422.html",
"chars": 1705,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>The change you wanted was rejected (422)</title>\n <meta name=\"viewport\" content="
},
{
"path": "spec/dummy/public/500.html",
"chars": 1635,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>We're sorry, but something went wrong (500)</title>\n <meta name=\"viewport\" conte"
},
{
"path": "spec/rails_core_spec_helper.rb",
"chars": 2962,
"preview": "# This file is copied to spec/ when you run 'rails generate rspec:install'\nrequire 'core_spec_helper'\nENV['RAILS_ENV'] |"
},
{
"path": "spec/spec_helper.rb",
"chars": 49,
"preview": "# file need to exist, otherwise specs will fail!\n"
},
{
"path": "spec/test/core/base/component/argument_spec.rb",
"chars": 1279,
"preview": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n before :al"
},
{
"path": "spec/test/core/base/component/conditional_rendering_spec.rb",
"chars": 2931,
"preview": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n before :al"
},
{
"path": "spec/test/core/base/component/core_namespaces_spec.rb",
"chars": 3673,
"preview": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n before :al"
},
{
"path": "spec/test/core/base/component/custom_namespaces_spec.rb",
"chars": 3946,
"preview": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n before :al"
},
{
"path": "spec/test/core/base/component/options_spec.rb",
"chars": 2370,
"preview": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n before :al"
},
{
"path": "spec/test/core/base/component/partials_spec.rb",
"chars": 2177,
"preview": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n before :al"
},
{
"path": "spec/test/core/base/component/prepare_spec.rb",
"chars": 1352,
"preview": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n before :al"
},
{
"path": "spec/test/core/base/component/properties_spec.rb",
"chars": 8574,
"preview": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe 'Properties Mechanism', type: :feature, js: true do\n\n "
},
{
"path": "spec/test/core/base/component/slots_spec.rb",
"chars": 4105,
"preview": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n before :al"
},
{
"path": "spec/test/core/base/component/static_rendering_spec.rb",
"chars": 1333,
"preview": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n before :al"
},
{
"path": "spec/test/core/base/component/url_params_access_spec.rb",
"chars": 1477,
"preview": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n before :al"
},
{
"path": "spec/test/core/base/component/view_context_access_spec.rb",
"chars": 1854,
"preview": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n before :all"
},
{
"path": "spec/test/core/base/component/yield_spec.rb",
"chars": 1298,
"preview": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n before :all"
},
{
"path": "spec/test/core/base/layout/layout_resolving_spec.rb",
"chars": 6107,
"preview": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe \"Layout Resolving\", type: :feature, js: true do\n\n befo"
},
{
"path": "spec/test/core/base/layout/layout_spec.rb",
"chars": 3210,
"preview": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe \"App\", type: :feature, js: true do\n\n before :all do\n "
},
{
"path": "spec/test/core/base/page/controller_instance_access_spec.rb",
"chars": 949,
"preview": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Page\", type: :feature, js: true do\n\n before :all do\n"
},
{
"path": "spec/test/core/base/page/orchestrates_components_spec.rb",
"chars": 940,
"preview": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Page\", type: :feature, js: true do\n\n before :all do\n"
},
{
"path": "spec/test/core/base/page/partials_spec.rb",
"chars": 3046,
"preview": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Page\", type: :feature, js: true do\n\n before :all do\n"
},
{
"path": "spec/test/core/base/page/prepare_spec.rb",
"chars": 1076,
"preview": "# require 'rails_core_spec_helper' \n# include CoreSpecUtils\n\n# describe \"Page\", type: :feature, js: true do\n\n# before "
},
{
"path": "spec/test/core/base/page/slots_spec.rb",
"chars": 1679,
"preview": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe \"Page\", type: :feature, js: true do\n\n before :all do\n "
},
{
"path": "spec/test/core/base/page/url_params_access_spec.rb",
"chars": 850,
"preview": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Page\", type: :feature, js: true do\n\n before :all do\n"
},
{
"path": "spec/test/core/base/page/view_context_access_spec.rb",
"chars": 1379,
"preview": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe \"Page\", type: :feature, js: true do\n\n before :all do\n "
},
{
"path": "spec/test/core/custom_component_spec.rb",
"chars": 1331,
"preview": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe 'Creating custom components', type: :feature, js: true "
},
{
"path": "spec/test/core/html_rendering/action_view_integration.rb",
"chars": 3896,
"preview": "require 'rails_core_spec_helper'\n\ndescribe 'Action View Integration', type: :feature do\n include CoreSpecUtils\n\n it \"u"
},
{
"path": "spec/test/core/html_rendering/default_tags_spec.rb",
"chars": 18523,
"preview": "require 'rails_core_spec_helper'\n\ndescribe 'Default Tags Rendering', type: :feature do\n include CoreSpecUtils\n\n descri"
},
{
"path": "spec/test/core/html_rendering/link_spec.rb",
"chars": 6465,
"preview": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe 'a Component', type: :feature, js: true do\n\n it 'Examp"
},
{
"path": "spec/test/core/rails_render_spec.rb",
"chars": 1061,
"preview": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe 'Rails View Component', type: :feature, js: true do\n\n "
},
{
"path": "spec/test/core/support/capybara.rb",
"chars": 672,
"preview": "require 'capybara/rspec'\nrequire 'capybara/rails'\nrequire \"selenium/webdriver\"\n\nrequire \"matestack/ui/core\"\n\nCapybara.se"
},
{
"path": "spec/test/core/support/core_spec_utils.rb",
"chars": 1460,
"preview": "module CoreSpecUtils\n\n def stripped(html_string)\n html_string\n .gsub(/>\\s+</, \"><\")\n .gsub(\"\\n\", \"\")\n "
},
{
"path": "spec/test/core/support/example_controller.rb",
"chars": 259,
"preview": "require_relative 'layout'\n\nclass ExampleController < ApplicationController\n include Matestack::Ui::Core::Helper\n\n layo"
},
{
"path": "spec/test/core/support/layout.rb",
"chars": 139,
"preview": "# used in specs only, look for the demo app here: ./demo/app.rb\n\nclass Layout < Matestack::Ui::Layout\n\n def response\n "
}
]
// ... and 6 more files (download for full content)
About this extraction
This page contains the full source code of the basemate/matestack-ui-core GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 206 files (302.9 KB), approximately 85.2k tokens, and a symbol index with 527 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.