Search code examples
rubysinatraslim-lang

Sinatra and Slim return Ruby function


I have a small web application built using Sinatra and uses Slim templates. In my functions.rb file, I defined a hash called $locations and I want to use a function to return values from within the hash. Here is what I have:

# functions.rb
$locations = Hash[
  'wa' => Hash[
    'capital' => 'Olympia'
  ],
  'or' => Hash[
    'capital' => 'Salem'
  ]
]
def foobar
  $locations.each do |key, value|
    $locations[key]['capital']
  end
end

My Slim file

/ layout.slim
div#capitals = foobar

When rendered, the page has a div with an ID of capitals, but the content is just the entire hash printed out with brackets. If I change the inside of the each do to this: puts $locations[key]['capital'] and run the function in the command line, it works perfectly. How can I get this to work in Sinatra?

Basically, I want to accomplish this PHP script with Ruby instead (be able to call the function anywhere in my script and have it print out the <div> tags):

<?php
$locations = array(
  'wa' => array(
    'capital' => 'Olympia'
  ),
  'or' => array(
    'capital' => 'Salem'
  )
);

function foobar($array) {
  foreach ($array as $key => $value) {
    echo "<div>" . $array[$key]['capital'] . "</div>";
  }
}
foobar($locations);

Solution

  • In your loop, value is the hash at that key. Additionally, you want to return the capitals to the caller. #each enumerates over the elements but returns the collection, not the values returned by the block at each iteration. You want #map (or #collect):

    def foobar
      $locations.map do |_key, value|
        value['capital']
      end
    end
    

    Or:

    def foobar
      $locations.values.map do |value|
        value['capital']
      end
    end
    

    UPDATE: I don't know a lot of Slim, but based on your PHP example it seems to me you want something like:

    - for capital in foobar
      div= capital