Support Online
Skip to main content

Adding Interactivity to a Ruby on Rails Application with Stimulus.js

🧠 Technical Summary

This guide shows you how to manage user interactions with minimal JavaScript code using Stimulus.js in Ruby on Rails projects. The goal is to create fast, targeted interactions on server-generated HTML rather than large SPA frameworks (React, Vue). Steps: Creating the Nested Post model, configuring the controller, installing Stimulus with Webpacker and using JavaScript controllers.


🎯 What You Will Learn in This Guide

  • Stimulus.js installation and integration in Rails projects,
  • Creating nested resources,
  • The logic of the concepts of Controller, Target and Action,
  • Developing user actions with Font Awesome,
  • The working principle of Turbolinks and Stimulus.

⚙️ 1. Creating a Nested Post Model

Create post model:

rails generate model Post body:text shark:references

This command associates the model Post with the model Shark and adds the key shark_id.

Set model relationship:

# ~/sharkapp/app/models/shark.rb
class Shark < ApplicationRecord
has_many :posts, dependent: :destroy
validates :name, presence: true, uniqueness: true
validates :facts, presence: true
end

dependent: :destroy, when a shark is deleted it also deletes all its posts.


🧩 2. Creating the Nested Resource Controller

Edit routes:

# ~/sharkapp/config/routes.rb
Rails.application.routes.draw do
resources :sharks do
resources :posts
end
root 'sharks#index'
end

Create PostsController:

nano app/controllers/posts_controller.rb
class PostsController < ApplicationController
before_action :get_shark

def create
@post = @shark.posts.create(post_params)
end

def destroy
@post = @shark.posts.find(params[:id])
@post.destroy
end

private

def get_shark
@shark = Shark.find(params[:shark_id])
end

def post_params
params.require(:post).permit(:body, :shark_id)
end
end

This controller manages the creation and deletion of posts associated with the variable @shark.


🧱 3. Editing Views with Widgets

Add snippets to sharks/show.html.erb:

<h2>Posts</h2>
<%= render 'sharks/posts' %>

<div data-controller="posts">
<button data-action="posts#showAll">Show Older Posts</button>
<div data-target="posts.show" style="visibility:hidden">
<%= render 'sharks/all' %>
</div>
</div>

data-controller, data-target and data-action are the three basic components of Stimulus.


⚡ 4. Stimulus and Webpacker Installation

Yarn Setup

sudo apt update
sudo apt install yarn

Add Webpacker Gem

# ~/sharkapp/Gemfile
gem 'turbolinks', '~> 5'
gem 'webpacker', '~> 4.x'

Install Gem:

bundle install
bundle exec rails webpacker:install

Stimulus Setup

bundle exec rails webpacker:install:stimulus

Webpack configuration:

// ~/sharkapp/app/javascript/packs/application.js
import &#123; Application &#125; from "stimulus"
import &#123; definitionsFromContext &#125; from "stimulus/webpack-helpers"

const application = Application.start()
const context = require.context("../controllers", true, /\.js$/)
application.load(definitionsFromContext(context))

This code automatically installs Stimulus controllers.

Security policy setting:

# ~/sharkapp/config/initializers/content_security_policy.rb
Rails.application.config.content_security_policy do |policy|
policy.connect_src :self, :https, 'http://localhost:3035', 'ws://localhost:3035' if Rails.env.development?
end

🧠 5. Interaction with Stimulus Particles

New post form (_posts.html.erb):

<div data-controller="posts">
<%= form_with model: [@shark, @shark.posts.build], data: { action: "posts#addBody" } do |form| %>
<%= form.text_area :body, placeholder: "Your post here", data: { target: "posts.body" } %>
<br>
<%= form.submit %>
<% end %>
<ul data-target="posts.add"></ul>
</div>

Task listing (_all.html.erb):

<% for post in @shark.posts %>
<ul>
<li class="post">
<%= post.body %>
<%= button_tag "Görevi Kaldır", data: { controller: "posts", action: "posts#remove" } %>
<%= button_tag "Beğen", data: { controller: "posts", action: "posts#upvote" } %>
</li>
</ul>
<% end %>

Each button triggers a different action on the Stimulus controller.


💻 6. Stimulus Controller Writing

// ~/sharkapp/app/javascript/controllers/posts_controller.js
import &#123; Controller &#125; from "stimulus"

export default class extends Controller {
static targets = ["body", "add", "show"]

addBody() {
let content = this.bodyTarget.value
this.addTarget.insertAdjacentHTML('beforebegin', "<li>" + content + "</li>")
}

showAll() {
this.showTarget.style.visibility = "visible"
}

upvote() {
let post = event.target.closest(".post")
post.insertAdjacentHTML('beforeend', '<i class="fa fa-check-circle"></i>')
}

remove() {
let post = event.target.closest(".post")
post.style.visibility = "hidden"
}
}

This controller manages adding, showing, liking and removing posts on the DOM.


❓ Frequently Asked Questions (FAQ)

1. Why should Stimulus be preferred over React?

It provides a lightweight and simple JavaScript layer in server-side renderings, eliminating the need for complex state management.

2. Do Stimulus and Turbolinks work together?

Yes, Turbolinks optimizes page transitions while Stimulus manages DOM interactions.

3. What do Controller, Target and Action do?

Controller: JS class, Target: element to be accessed, Action: method that manages events.

4. Why was Font Awesome used?

To visually indicate actions such as post likes.

5. Where should I put the stimulation controllers?

app/javascript/controllers folder; Webpacker detects this directory automatically.


🎯 Result

You can now create small but effective interactions with Stimulus.js in your Ruby on Rails application. This approach provides a modern user experience while maintaining the classic MVC structure.

💡 Test your Stimulus-powered Rails application on the GenixNode platform now!