水口玄造 水口玄造 - 3 months ago 10
Ruby Question

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);

mwp mwp
Answer

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
Comments