Search code examples
rubysinatraslim-lang

How do I write Slim helpers in Sinatra?


I'm using Sinatra and Slim. I'm trying to work out how to write a helper for Slim so I can DRY-up my templates. (In this case the helper is small and I could get away with in-line Ruby, but in future I would do more complex things).

I have the following helper (expanded for debugging) in the file lib/slim_helpers.rb:

module SlimHelpers

  # foo converts strings like 'AWS::AutoScaling::AutoScalingGroup'
  # to 'Auto Scaling Group'
  def foo(input, &block)
    last = input.split('::')[-1]
    result = last.gsub(/([A-Z])/, ' \1').lstrip
    puts "result: #{result}"
    yield result
  end

end

I have the following (simplified) Sinatra app:

require 'sinatra/base'
require 'slim'
require_relative 'lib/slim_helpers.rb'

class SinatraApp < Sinatra::Base
  include SlimHelpers

  get '/' do
    puts '==> in /'
    @result = Bar.bar('dev')
    slim :qux
  end

end

In my template, I have the following piece of code:

- result.resources.each do |r|
  div class="list-group"
    div class="list-group-item active"
      h5 class="list-group-item-heading"
      = foo r["ResourceType"]

However, I'm getting the following error when I render the webpage:

LocalJumpError at /some/url
no block given (yield)
file: slim_helpers.rb location: foo line: 9
BACKTRACE
/Path/lib/slim_helpers.rb in foo
  yield result
/Path/views/asg.slim in block (3 levels) in singleton class
  = foo r["ResourceType"]
... etc

So I'm wondering what would be the block here, and how I would pass input to, and return results from, my foo function?


Solution

  • You don’t need a block at all, simply return the string and it will be included at that point in your template:

    def foo(input)
      last = input.split('::')[-1]
      result = last.gsub(/([A-Z])/, ' \1')
      puts "result: #{result}"
      result # or 'return result' if you prefer
    end
    

    As an aside, with Sinatra you would usually use helpers SlimHelpers rather than include SlimHelpers (although helpers is implemented by simply calling include).