Интеграция с Ruby on Rails

Stimulus — это легковесный JavaScript-фреймворк, ориентированный на поведение элементов страницы. В связке с Ruby on Rails он позволяет создавать интерактивные интерфейсы без сложной клиентской архитектуры. Rails предоставляет встроенные возможности для подключения Stimulus через Hotwire и Webpacker/Importmaps, что делает интеграцию максимально удобной.


Подключение Stimulus через Importmap (Rails 7+)

Rails 7 по умолчанию использует Importmap, позволяющий подключать JavaScript-библиотеки без сборщиков типа Webpack.

  1. Добавление Stimulus в проект:
bin/importmap pin stimulus
  1. Создание контроллеров:
bin/rails generate stimulus имя_контроллера

Эта команда создаст структуру файлов:

app/javascript/controllers/имя_контроллера_controller.js
  1. Подключение контроллеров в application.js:
import { Application } from "@hotwired/stimulus"
import { definitionsFromContext } from "@hotwired/stimulus-loading"

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

Структура Stimulus-контроллера

Контроллер Stimulus состоит из нескольких основных частей:

  • targets — элементы, с которыми работает контроллер.
  • values — параметры для конфигурирования поведения.
  • actions — события, на которые реагирует контроллер.

Пример контроллера кнопки «Like»:

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["button", "count"]
  static values = { count: Number }

  connect() {
    console.log(`Начальное значение лайков: ${this.countValue}`)
  }

  increment() {
    this.countValue++
    this.countTarget.textContent = this.countValue
  }
}

HTML-разметка для данного контроллера:

<div data-controller="like" data-like-count-value="0">
  <button data-action="click->like#increment" data-like-target="button">Like</button>
  <span data-like-target="count">0</span>
</div>

Интеграция с Rails UJS и формами

Stimulus отлично работает с AJAX-формами Rails через Turbo. Пример обновления списка комментариев без перезагрузки страницы:

  1. Контроллер комментариев:
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["comments", "form"]

  submit(event) {
    event.preventDefault()
    const formData = new FormData(this.formTarget)

    fetch(this.formTarget.action, {
      method: "POST",
      body: formData,
      headers: { "Accept": "text/vnd.turbo-stream.html" }
    })
  }
}
  1. HTML-структура:
<div data-controller="comments">
  <div data-comments-target="comments">
    <%= render @comments %>
  </div>
  <%= form_with model: Comment.new, data: { action: "submit->comments#submit" } do |f| %>
    <%= f.text_area :body %>
    <%= f.submit "Add Comment" %>
  <% end %>
</div>
  1. Turbo Stream отвечает обновлением comments-target, обеспечивая мгновенное отображение новых комментариев.

Использование Stimulus с Turbo Frames и Turbo Streams

Turbo Frames позволяют изолировать части страницы для обновления, что отлично сочетается с контроллерами Stimulus.

Пример:

<turbo-frame id="cart">
  <div data-controller="cart" data-cart-items-value="<%= @cart.items.count %>">
    <%= render @cart.items %>
  </div>
</turbo-frame>

Контроллер может управлять состоянием корзины без вмешательства в остальную страницу:

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static values = { items: Number }

  connect() {
    this.updateBadge()
  }

  addItem() {
    this.itemsValue++
    this.updateBadge()
  }

  updateBadge() {
    document.querySelector("#cart-badge").textContent = this.itemsValue
  }
}

Организация больших проектов

В больших Rails-приложениях рекомендуется:

  • Использовать namespaced controllers, чтобы избежать конфликтов.

    app/javascript/controllers/admin/users_controller.js
  • Разделять контроллеры по функциональным зонам страницы.

  • Применять targets и values для минимизации поиска DOM элементов через querySelector.

  • Использовать actions вместо прямой привязки обработчиков через JavaScript.


Практические советы

  • События DOMContentLoaded не нужны при использовании Stimulus, так как connect() автоматически вызывается при инициализации.
  • Для динамически добавленных элементов через Turbo Streams важно использовать turbo:load или обновлять контроллеры через application.load() повторно.
  • Минимизировать прямую манипуляцию DOM и опираться на targets и values, чтобы код оставался чистым и тестируемым.
  • Stimulus не конфликтует с другими JS-библиотеками, но рекомендуется держать взаимодействие через события или отдельные контроллеры.

Stimulus в связке с Ruby on Rails обеспечивает простую, но мощную архитектуру для интерактивного фронтенда, оставляя серверу роль обработки данных и логики, а клиенту — управление поведением элементов страницы. Контроллеры легко масштабируются, интегрируются с Turbo, формами и другими Rails-инструментами, что делает их идеальным выбором для современных Rails-приложений.