As a Rails Engine, matestack deeply integrates a Vue.js based UI into Rails, offering optional prebuilt components. Use it to write dynamic Web-UIs with minimum effort and maximum dev happiness in pure Ruby. The main goals are:
- Reduction of complexity of modern web development, moving front and backend closer together
- More maintainable UI code, using a component-based structure written in Ruby
- Increased development speed and happiness, offering prebuilt UI-Components for classic requirements
- Modern, dynamic UI feeling without the need to implement a separate JavaScript Application
matestack can progressively replace the classic Rails-View-Layer. You are able to use it alongside your classic views and incrementally turn your Rails-App into a dynamic Web-App.
Click here to see how you can add Matestack UI to your existing Rails application: Installation Guide
class Pages::MyPage < Matestack::Ui::Page
def prepare
@technologies = ["Rails", "Vue.js", "Trailblazer", "Rspec", "Capybara"]
end
def response
components{
div id: "technologies" do
@technologies.each do |technology|
plain "matestack uses #{technology}"
end
end
}
end
end
class Apps::MyApp < Matestack::Ui::App
def response
components{
header do
heading size: 1, text: "My App"
end
nav do
transition path: :my_first_page_path do
button text: "Page 1"
end
transition path: :my_second_page_path do
button text: "Page 2"
end
end
main do
page_content #pages are dynamically yielded here, when buttons are clicked!
end
footer do
plain "That's it!"
end
}
end
end
class Pages::MyApp::MyFirstPage < Matestack::Ui::Page
def response
components{
div id: "div-on-page-1" do
plain "My First Page"
end
}
end
end
class Pages::MyApp::MySecondPage < Matestack::Ui::Page
def response
components{
div id: "div-on-page-2" do
plain "My Second Page"
end
}
end
end
class Pages::MyPage < Matestack::Ui::Page
def response
components {
action my_action_config do
button text: "Click me!"
end
#content gets rerendered without page reload if action succeeded
async rerender_on: "my_action_succeeded" do
div id: "my-div" do
plain DateTime.now
end
end
}
end
def my_action_config
{
method: :post,
path: :some_rails_routing_path,
success: {
emit: "my_action_succeeded"
}
}
end
end
class Pages::MyApp::MyFirstPage < Matestack::Ui::Page
def prepare
@my_model = MyModel.new
end
def response
components {
form my_form_config, :include do
form_input key: :some_model_attribute, type: :text
form_submit do
button text: "Submit me!"
end
end
async show_on: "form_has_errors", hide_after: 5000 do
plain "Data could not be submitted, please check form"
end
}
end
def my_form_config
{
for: @my_model,
method: :post,
path: :some_action_path,
success: {
transition: {
path: :my_second_page_path,
}
},
failure: {
emit: "form_has_errors"
}
}
end
end
class Pages::MyPage < Matestack::Ui::Page
def prepare
@comments = Comment.last(5)
end
def response
components {
#content gets rerendered without page reload when
#websocket event is received
async rerender_on: "comments_changed" do
@comments.each do |comment|
div do
plain comment.content
end
end
end
}
end
end
somewhere else on the backend:
ActionCable.server.broadcast("matestack_ui_core", {
message: "comments_changed"
})
Documentation can be found here
Changelog can be found here
We're currently finalizing the roadmap towards to a stable 1.0 release, supposed to happen towards the end of the year! For details make sure to check the release management project and get in touch via our chat for feedback!
As a low-barrier feedback channel for our early users, we have set up a Gitter chat that can be found here. You are very welcome to ask questions and send us feedback there!
We are happy to accept contributors of any kind. Please refer to the Contribution Guide
The gem is available as open source under the terms of the MIT License.