datastar/sdk/ruby/README.md

5.8 KiB

Datastar Ruby SDK

Implement the Datastart SSE procotocol in Ruby. It can be used in any Rack handler, and Rails controllers.

Installation

Install the gem and add to the application's Gemfile by executing:

bundle add datastar

Or point your Gemfile to the source

gem 'datastar', git: 'https://github.com/starfederation/datastar', glob: 'sdk/ruby/*.gemspec'

Usage

Initialize the Datastar dispatcher

In your Rack handler or Rails controller:

# Rails controllers, as well as Sinatra and others, 
# already have request and response objects

datastar = Datastar.new(request:, response:, view_context: self)

# In a Rack handler, you can instantiate from the Rack env
datastar = Datastar.from_rack_env(env)

Sending updates to the browser

There are two ways to use this gem in HTTP handlers:

  • One-off responses, where you want to send a single update down to the browser.
  • Streaming responses, where you want to send multiple updates down to the browser.

One-off update:

datastar.merge_fragments(%(<h1 id="title">Hello, World!</h1>))

In this mode, the response is closed after the fragment is sent.

Streaming updates

datastar.stream do |sse|
  sse.merge_fragments(%(<h1 id="title">Hello, World!</h1>))
  # Streaming multiple updates
  100.times do |i|
    sleep 1
    sse.merge_fragments(%(<h1 id="title">Hello, World #{i}!</h1>))
  end
end

In this mode, the response is kept open until stream blocks have finished.

Concurrent streaming blocks

Multiple stream blocks will be launched in threads/fibers, and will run concurrently. Their updates are linearized and sent to the browser as they are produced.

# Stream to the browser from two concurrent threads
datastar.stream do |sse|
  100.times do |i|
    sleep 1
    sse.merge_fragments(%(<h1 id="slow">#{i}!</h1>))
  end
end

datastar.stream do |sse|
  1000.times do |i|
    sleep 0.1
    sse.merge_fragments(%(<h1 id="fast">#{i}!</h1>))
  end
end

See the examples directory.

Datastar methods

All these methods are available in both the one-off and the streaming modes.

merge_fragments

See https://data-star.dev/reference/sse_events#datastar-merge-fragments

sse.merge_fragments(%(<div id="foo">\n<span>hello</span>\n</div>))

# or a Phlex view object
sse.merge_fragments(UserComponet.new)

# Or pass options
sse.merge_fragments(
  %(<div id="foo">\n<span>hello</span>\n</div>),
  merge_mode: 'append'
)

remove_fragments

See https://data-star.dev/reference/sse_events#datastar-remove-fragments

sse.remove_fragments('#users')

merge_signals

See https://data-star.dev/reference/sse_events#datastar-merge-signals

sse.merge_signals(count: 4, user: { name: 'John' })

remove_signals

See https://data-star.dev/reference/sse_events#datastar-remove-signals

sse.remove_signals(['user.name', 'user.email'])

execute_script

See https://data-star.dev/reference/sse_events#datastar-execute-script

sse.execute_scriprt(%(alert('Hello World!'))

signals

See https://data-star.dev/guide/getting_started#data-signals

Returns signals sent by the browser.

sse.signals # => { user: { name: 'John' } }

redirect

This is just a helper to send a script to update the browser's location.

sse.redirect('/new_location')

Lifecycle callbacks

on_connect

Register server-side code to run when the connection is first handled.

datastar.on_connect do
  puts 'A user has connected'
end

on_client_disconnect

Register server-side code to run when the connection is closed by the client

datastar.on_client_connect do
  puts 'A user has disconnected connected'
end

on_server_disconnect

Register server-side code to run when the connection is closed by the server. Ie when the served is done streaming without errors.

datastar.on_server_connect do
  puts 'Server is done streaming'
end

on_error

Ruby code to handle any exceptions raised by streaming blocks.

datastar.on_error do |exception|
  Sentry.notify(exception)
end

Note that this callback can be registered globally, too.

Global configuration

Datastar.configure do |config|
  config.on_error do |exception|
    Sentry.notify(exception)
  end
end

Rails

Rendering Rails templates

datastar.stream do |sse|
  10.times do |i|
    sleep 1
    tpl = render_to_string('events/user', layout: false, locals: { name: "David #{i}" })
    sse.merge_fragments tpl
  end
end

Rendering Phlex components

#merge_fragments supports Phlex component instances.

sse.merge_fragments(UserComponent.new(user: User.first))

Tests

bundle exec rspec

Running Datastar's SDK test suite

Install dependencies.

bundle install

From this library's root, run the bundled-in test Rack app:

bundle puma examples/test.ru

Now run the test bash scripts in the test directory in this repo.

./test-all.sh http://localhost:9292

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and the created tag, and push the .gem file to rubygems.org.

Contributing

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