0.01
A long-lived project that still receives updates
Opal Stimulus provides a way to write Stimulus controllers in Ruby, leveraging the Opal compiler to convert Ruby code into JavaScript. This allows developers familiar with Ruby to use the Stimulus framework without needing to write JavaScript directly.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Development

~> 1.2

Runtime

~> 3.9.0
~> 1.8.2
~> 0.1.1
>= 7.2, < 8.0.3
 Project Readme

Opal Stimulus for Rails

Write your Stimulus controllers in Ruby instead of JavaScript! 🎉

Opal Stimulus uses the Opal Ruby-to-JavaScript compiler to bring the elegance of Ruby to your frontend controllers. If you love Ruby and prefer its syntax over JavaScript, this gem is for you.

Compatibility: Rails 7.2+ to 8.0.2

Ruby

Quick Start

Add to your Rails app and get started in seconds:

bundle add opal_stimulus
rails opal_stimulus:install
bin/dev

Generate your first Ruby controller:

bin/rails generate opal_stimulus hello

This creates app/opal/controllers/hello_controller.rb. If you have an existing JavaScript controller, you can remove it:

bin/rails destroy stimulus hello  # removes app/javascript/controllers/hello_controller.js

Example: Hello World

Here's the classic Stimulus example, but in Ruby! Compare with the JavaScript version.

Ruby Controller (app/opal/controllers/hello_controller.rb):

class HelloController < StimulusController
  self.targets = ["name", "output"]

  def greet
    output_target.text_content = "Hello, #{name_target.value}!"
  end
end

HTML (unchanged from regular Stimulus):

<div data-controller="hello">
  <input data-hello-target="name" type="text">
  <button data-action="click->hello#greet">Greet</button>
  <span data-hello-target="output"></span>
</div>

Key Differences from JavaScript Stimulus

  • Snake case: JavaScript's containerTarget becomes container_target in Ruby
  • DOM objects: All target, element, document, window, and event objects are JS::Proxy instances that provide Ruby-friendly access to JavaScript APIs
  • HTML stays the same: Your templates and data attributes work exactly like regular Stimulus

Reference Examples

Based on the Stimulus Reference, here's how common patterns work in Ruby:

Lifecycle Callbacks

📚 Stimulus Lifecycle Callbacks Reference

class AlertController < StimulusController
  def initialize; end
  def connect; end
  def disconnect; end
end

Actions & Events

📚 Stimulus Actions Reference

class WindowResizeController < StimulusController
  def resized(event)
    if !@resized && event.target.inner_width >= 1080
      puts "Full HD detected!"
      @resized = true
    end
  end
end

Targets

📚 Stimulus Targets Reference

class ContainerController < StimulusController
  self.targets = ["container"]

  def container_target_connected
    container_target.inner_html = <<~HTML
      <h1>Test connected!</h1>
    HTML
  end

  def container_target_disconnected
    puts "Container disconnected!"
  end
end

Outlets

📚 Stimulus Outlets Reference

class ChatController < StimulusController
  self.outlets = [ "user-status" ]

  def connect
    user_status_outlets.each do |status|
      puts status
    end
  end
end

Values

📚 Stimulus Values Reference

class LoaderController < StimulusController
  self.values = { url: :string }

  def connect
    window.fetch(url_value).then do |response|
      response.json().then do |data|
        load_data(data)
      end
    end
  end

  private

  def load_data(data)
    # ...
  end
end

CSS Classes

📚 Stimulus CSS Classes Reference

class SearchController < StimulusController
  self.classes = ["loading"]

  def load_results
    element.class_list.add(loading_class)
  end
end

Working with the DOM

Opal Stimulus gives you Ruby-friendly access to all the browser APIs you know and love:

window

class WindowController < StimulusController
  def connect
    window.alert "Hello world!"
    window.set_timeout(-> {
      puts "1. Timeout test OK (1s delay)"
    }, 1000)
  end
end

document

class DocumentController < StimulusController
  def connect
    document.querySelectorAll("h1").each do |h1|
      h1.text_content = "Opal is great!"
    end
  end
end

Development

Run the test suite:

bundle exec rake

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/josephschito/opal_stimulus.

License

The gem is available as open source under the terms of the MIT License.