rubyerb

Replacing if in ERB with a method


I want to replace this code

---
myyaml:
  me:
    :name: "John"
  text: |
    My name is <% if me %><%= me[:name] %><% end %>
---

With something like this:

---
myyaml:
  me:
    :name: "John"
  text: |
    My name is <%=greetings()%>
---

The idea is to define greetings function outside file and call as result_with_hash in ERB class.

The desired result is, obviously, My name is John.


Solution

  • One thing to note is ERB#result_with_hash states:(emphasis added)

    result_with_hash(hash)

    Render a template on a new toplevel binding with local variables specified by a Hash object.

    So in your case you are trying to call a method greetings() which is fine and completely accessible but it negates any reason for using result_with_hash. If you wanted to you could use a local variable greeting instead and call the method to assign the value.

    require 'yaml'
    require 'erb'
    yaml =<<DOC
    ---
    myyaml:
      me:
        :name: "John"
      text: |
        My name is <%=greeting%>
    ---
    DOC
    
    # You used both String and Symbol keys would recommend picking one so this isn't as awkward
    name = YAML.load(yaml).dig('myyaml','me',:name)
    
    def greetings(name) 
      "#{name}!" 
    end 
    
    puts ERB.new(yaml).result_with_hash(greeting: greetings(name))
    #=> ---
    #myyaml:
    #  me:
    #    :name: "John"
    #  text: |
    #    My name is John!
    #---
    

    The other option would be to just use ERB#result rather than result_with_hash. Both result and result_with_hash will use the current binding so instance variables, local variables (not overridden by the Hash provided to result_with_hash) and methods are all accessible in the ERB template.

    require 'yaml'
    require 'erb'
    yaml =<<DOC
    ---
    myyaml:
      me:
        :name: "John"
      text: |
        My name is <%=greetings()%>
    ---
    DOC
    
    # You used both String and Symbol keys would recommend picking one so this isn't as awkward
    @name = YAML.load(yaml).dig('myyaml','me',:name)
    
    def greetings = "#{@name}!" 
    
    puts ERB.new(yaml).result
    #=> ---
    #myyaml:
    #  me:
    #    :name: "John"
    #  text: |
    #    My name is John!
    #---