jeremyevans/roda

Raises "Unsupported block result" when using Unreloader and json plugin

Closed this issue ยท 2 comments

Hi Jeremy, I am getting a Roda::RodaError: unsupported block result using Ruby 3.1.3 on an M1 Mac.

Let me admit, that I am not 100 % sure whether it's a bug or not. ๐Ÿ™ˆ

It's a basic Roda example using Unreloader.

Here's the example code that provokes the error:

# app.rb
class App < Roda
  use Rack::Deflater # <<- enable gzip

  plugin :json

  route do |r|
    r.root do
      { hello: 'world',
        lorem: 'lorem ipsum dolor sit amet!' }
    end

    # /:int
    r.on Integer do |x|
      # /:int
      r.on Integer do |y|
        { data: {add: x + y,
      multiply: x * y} }
      end
    end
  end
end
# config.ru
require 'rubygems'
require 'bundler/setup'
Bundler.require

require 'rackup'
require 'rack/deflater'
require 'rack/unreloader'
require 'roda'

Unreloader = Rack::Unreloader.new{App}

Unreloader.require 'app.rb'
run Unreloader
# Gemfile

# frozen_string_literal: true

source "https://rubygems.org"

# gem "rails"

gem "rack", "~> 3.0"
gem "rackup", "~> 0.2.3"
gem "roda", "~> 3.62"
gem "webrick", "~> 1.7"
gem "rack-unreloader", "~> 2.0"

After the initial rackup everything is fine, but changing something in the return value of the hash yielding the math results - it's when the crash appears.

Roda::RodaError: unsupported block result: {:data=>{:add=>6, :multiply=>8}}
/usr/local/rvm/gems/default/gems/roda-3.62.0/lib/roda/request.rb:550:in `block_result_body'
/usr/local/rvm/gems/default/gems/roda-3.62.0/lib/roda/request.rb:95:in `block_result'
/usr/local/rvm/gems/default/gems/roda-3.62.0/lib/roda/request.rb:603:in `if_match'
/usr/local/rvm/gems/default/gems/roda-3.62.0/lib/roda/request.rb:241:in `on'

using to_json does work as expected, though.

# ... shortened

    # /:int
    r.on Integer do |x|
      # /:int
      r.on Integer do |y|
        { data: {add: x + y,
      multiply: x * y} }.to_json
      end
    end

# ... shortened

Thank you very much for posting a reproducible example. This turns out not to be a Roda issue. What happens is that rack-unreloader unloads all constants added by the require 'app.rb' call, which is much more than App. One way to see the problem is to add a rack-unreloader logger:

require 'logger'
Unreloader = Rack::Unreloader.new(:logger=>Logger.new($stdout)){App}

That shows the problem. When you modify the app.rb file, it unloads a bunch of constants you don't want it to unload. You can fix the problem by specifying which constants to unload when the app.rb file changes:

Unreloader.require('app.rb'){:App}

The rack-unreloader README discusses this issue, please see:

It would be nice if there was a better default behavior for rack-unreloader, but unfortunately I cannot think of one that doesn't involve modifying core methods such as require, which explicitly is against rack-unreloader's design.

Thank you so much for giving direction!

I was able to have hot reloading working with plugin :hash_routes, finally. Took some inspiration from the code in roda-sequel-stack, too!