简体   繁体   中英

Loop through block in rails helper

I'm trying to create a Rails helper that takes a block and loops through that to produce:

<span data-param1="param1" data-param2="param2">
    <span data-options="test">
    <span data-options="test">
</span>

An example of the helper in use:

<%= main(param1, param2) do %>
<%= sub('param', :options => 'test') %>
<%= sub('param', 'test') %>
<% end %>

And then the helper itself:

module MyHelper

  def main(param1, param2, &block)
    raise ArgumentError.new('Missing block!') unless block_given?
    content_tag :span, :data => { :param1 => param1, :picture => '' } do
      markup = content_tag(:span, '', :data => { :param2 => param2 }).to_s

      #loop through blocks of subs
      &block.each do |item|
        sub = sub(item.param, item.options)
        data = { :param => param }
        data[:options] = sub.options unless sub.options.blank?
        markup << content_tag(:span, '', :data => data).to_s
      end

    markup
  end

  private

  def sub(param, options = {})
    options = extract_options!(options)
  end

  # returns a string
  def extract_options!(options)
    when String
      options
    when Hash
      #removed for this question
    else
      raise ArgumentError.new('Only Hash && String allowed!')
  end

end

Note: I've removed the Hash handling in the extract_options to keep the question code short.

However it doesn't like the &block loop and gives this error:

syntax error, unexpected &, expecting keyword_end
      &block.each do |item|
       ^

First of all, block basically is a Proc instance and Proc does not by any mean implements Enumerable , hence calling each on it won't succeed in any case.

I wonder, what's wrong with passing an array to main ? What are you trying to achieve?

The code example that works:

def main(param1, param2, *subs)
  ...
  subs.each ...
end

<%= main(param1, param2, sub('param', :options => 'test'), sub('param', 'test')) %>

Whether you still want to use a block (why?):

def main(param1, param2, &block)
  ...
  yield.each ...
end

<%= main param1, param2 do %>
<%= [sub('param', :options => 'test'), sub('param', 'test')] %>
<% end %>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM