Link_to meta programming question

I am trying to create a dynamic menu using the following construct:

<%- menu_list = [ ‘first’, ‘second’, ‘third’] -%>

    <%- menu_list.each do |m| -%> <%= link_to "List All #{m.titlecase.pluralize} _path %> <%- end -%>

What I cannot determine is what I have to do to replace so that the
link_to has a target. I have tried string substitution ("#{m}"_path)
but that gives a compile error:

_erbout.concat(( link_to “List All #{m.titlecase.pluralize}”,
("#{m}"_path) ).to_s); _erbout.concat "

I am sure that there must be a fairly straight forward way to do this.
Can someone point it out to me?

On May 1, 2008, at 20:58 , James B. wrote:

the
link_to has a target.

You can get it this way:

<%= link_to "List All #{m.titlecase.pluralize}", send("#{m}_path")

%>

Nevertheless in this case I tend to see repetition as a better option.
Compare the above to this crystal clear

<%= link_to "List All Firsts", first_path %>
<%= link_to "List All Seconds", second_path %>
<%= link_to "List All Thirds", third_path %>

If you have 35 of those then fine, but for a handful of them I find
copy & paste gives better code.

– fxn

Xavier N. wrote:

On May 1, 2008, at 20:58 , James B. wrote:

the
link_to has a target.

You can get it this way:

<%= link_to "List All #{m.titlecase.pluralize}", send("#{m}_path")

%>

Nevertheless in this case I tend to see repetition as a better option.
Compare the above to this crystal clear

<%= link_to "List All Firsts", first_path %>
<%= link_to "List All Seconds", second_path %>
<%= link_to "List All Thirds", third_path %>

If you have 35 of those then fine, but for a handful of them I find
copy & paste gives better code.

– fxn

Thank you.

My example was cut down to the essentials to avoid clutter and focus on
the my present issue. There are many related bits to each ‘m’ that have
a similar construction so that meta programming this represents a clear
advantage over cut and paste.

Now I have a related question. Some of these methods may or may not
have routes depending upon when and where they are invoked. So, I have a
guard conditional set up:

<%- role_list.each do |m| -%>

  • <%= "#{m.titlecase}" %>

    <%= if defined? “#{m.pluralize}_path” then
    link_to “List All #{m.titlecase.pluralize}”,
    send("#{m.pluralize}_path")
    else
    nil
    end %>


  • <%- end -%>

    When the guard is explicit ( if defined? firsts_path then …) this
    works. But I do not know how to test for a dynamically formed method
    name. How is this done in Ruby?

    2008/5/1 James B. [email protected]:

    Now I have a related question. Some of these methods may or may not
    have routes depending upon when and where they are invoked. So, I have a
    guard conditional set up:

    <%- role_list.each do |m| -%>

  • <%= "#{m.titlecase}" %>

    <%= if defined? “#{m.pluralize}_path” then

  • When the guard is explicit ( if defined? firsts_path then …) this
    works. But I do not know how to test for a dynamically formed method
    name. How is this done in Ruby?

    Yeah, defined? is not what you want in that case:

    irb(main):001:0> defined? “foo”
    => “expression”

    Use respond_to? instead.

    Xavier N. wrote:

    2008/5/1 James B. [email protected]:

    Yeah, defined? is not what you want in that case:

    irb(main):001:0> defined? “foo”
    => “expression”

    Use respond_to? instead.

    Works great using either idiom: Thanks!

      <%- role_list.each do |m| -%>
    • <%= "#{m.titlecase}" %> <%= link_to "List All #{m.titlecase.pluralize}", send("#{m.pluralize}_path") \ if respond_to? "#{m.pluralize}_path" %> <%= if respond_to? "#{m.pluralize}_path" then link_to "List All #{m.titlecase.pluralize}", send("#{m.pluralize}_path") else nil end %>
    • <%- end -%>

    Can you explain to me the different behaviours between defined? and
    respond_to? in this instance. I am not clear why defined? would work
    with symbolized path names but not work with the same parameterized
    string.to_sym.

    Thanks again.

    On Thu, May 1, 2008 at 11:54 PM, James B.
    [email protected] wrote:

    Can you explain to me the different behaviours between defined? and
    respond_to? in this instance. I am not clear why defined? would work
    with symbolized path names but not work with the same parameterized
    string.to_sym.

    respond_to? asks whether the object responds to some method. Since you
    want to know whether self responds to the path generator that’s the
    one.

    defined? is more generic. That’s a special operator in the sense that
    Ruby does not evaluate its argument. I don’t know the whole story
    (anyone?) but a posteriori defined? works at parse time or something
    like that to interpret the argument expression in a special way.

    For example, if SOME_CONSTANT is unknown

    defined? SOME_CONSTANT

    does not raise NameError, it does not evaluate the argument. It
    silently returns nil. If the constant was known it would return
    “constant”.

    Check this other one for example:

    irb(main):004:0> a = “\n”
    => “\n”
    irb(main):005:0> defined? a.chop!
    => “method”
    irb(main):006:0> a
    => “\n”

    You see? chop! is not being called, we are just told that a responds to
    chop!.

    I’d like to provide a better explanation of defined? but don’t have
    Flanagan & Matz at hand.

    Xavier N. wrote:

    I’d like to provide a better explanation of defined? but don’t have
    Flanagan & Matz at hand.

    The main point that I see here is that when I am testing for the
    existence of methods then I should use respond_to? and that is
    sufficient.

    On 1 May 2008, at 23:24, Xavier N. wrote:

    want to know whether self responds to the path generator that’s the
    one.

    defined? is more generic. That’s a special operator in the sense that
    Ruby does not evaluate its argument. I don’t know the whole story
    (anyone?) but a posteriori defined? works at parse time or something
    like that to interpret the argument expression in a special way.

    defined? is a bit nuts:
    http://redhanded.hobix.com/inspect/methodCheckDefined.html

    For more on defined? see:

    http://redhanded.hobix.com/inspect/methodCheckDefined.html

    I wrote too soon. I have another blank spot in my knowledge that need
    filling.

    This construct works:

      <%- role_list.each do |m| -%>
    • <%= "#{m.titlecase}" if respond_to? "#{m.pluralize}_path" %> <%= link_to "List All #{m.titlecase.pluralize}", \ send("#{m.pluralize}_path") if respond_to? "#{m.pluralize}_path" %> <%= link_to "Add New #{m.titlecase}", send("new_#{m}_path") \ if respond_to? "#{m.pluralize}_path" %>
    • <%- end -%>

    and this does not:

      <%- role_list.each do |m| -%>
    • <%= if respond_to? "#{m.pluralize}_path" then "#{m.titlecase}" link_to "List All #{m.titlecase.pluralize}", send("#{m.pluralize}_path") link_to "Add New #{m.titlecase}", send("new_#{m}_path") end -%>
    • <%- end -%>

    All I get in the html from this is the output of the last step in the if
    block:

    link_to “Add New #{m.titlecase}”, send(“new_#{m}_path”)

    This indicate that I am only getting the final return value of a Ruby
    method as the entire result of the if construct. This is not what I
    intend or desire so is there some way of getting each step in the if
    block to produce output onto the html page?

    Xavier N. wrote:

    if is an expression in Ruby, but the easy way to do that in ERb is

    <% if … %>
    this
    that
    <%= link_to … %>
    <% end %>

    Note the use of <% … %> instead of <%= … %>.

    I tried that syntax first and could not get it to work. I have since
    discovered why. I kept leaving the trailing -%> off of the “if”
    statement. Sigh.

    Thanks again.

    On Fri, May 2, 2008 at 6:40 PM, James B.
    [email protected] wrote:

    send(“#{m.pluralize}path")
    link_to “Add New #{m.titlecase}”, send("new
    #{m}_path”)

    This indicate that I am only getting the final return value of a Ruby
    method as the entire result of the if construct. This is not what I
    intend or desire so is there some way of getting each step in the if
    block to produce output onto the html page?

    if is an expression in Ruby, but the easy way to do that in ERb is

    <% if … %>
    this
    that
    <%= link_to … %>
    <% end %>

    Note the use of <% … %> instead of <%= … %>.

    Me again.

    Now that I have this working in a view I want to move it all out into a
    pair of methods that I can call from multiple views: role_list_head and
    role_list_foot. Two questions arise from this:

    Where do I put these methods? In application_helper.rb,
    application_controller.rb, or somewhere else?

    What does the method look like? Something akin to this I expect:

    @role_list_default = [‘entity’, ‘client’, ‘employee’, ‘vendor’]

    def role_list_head(list=@role_list_default)
    link_to ‘Main Page’, :controller => ‘nav_menus’
    list.each do |m|
    # guard against missing path methods.
    if respond_to? “#{m.pluralize}_path” then
    link_to “List All #{m.titlecase.pluralize}”,
    send("#{m.pluralize}path")
    end
    end
    list.each do |m|
    if respond_to? "new
    #{m.}path" then
    link_to “Add New #{m.titlecase}”, send("new
    #{m}_path")
    end
    end
    end

    I know that this does not work, because I tried it. But something
    somewhat like this has to be the answer.

    On Fri, May 2, 2008 at 9:04 PM, James B.
    [email protected] wrote:

    What does the method look like? Something akin to this I expect:

    @role_list_default = [‘entity’, ‘client’, ‘employee’, ‘vendor’]

    This could be a constant.

    end
    

    somewhat like this has to be the answer.
    That’s view stuff so should go to a helper or to a partial. The helper
    would build and return a single string with HTML so that you can use
    it like this

    <%= role_list_header %>

    On Fri, May 2, 2008 at 11:06 PM, James B.
    [email protected] wrote:

    That’s view stuff so should go to a helper or to a partial. The helper
    would build and return a single string with HTML so that you can use
    it like this

    <%= role_list_header %>

    yes, but which helper file exactly? All that I have read about helpers
    indicates that they are tied to a specific controller by name. I tried
    adding a dummy method to a file called lib/application_helper.rb but
    when I called the method from a view I got a missing method error.

    There are several options, but you can just throw it into
    app/helpers/application_helper.rb. That file contains helpers that are
    available everywhere.

    Xavier N. wrote:

    That’s view stuff so should go to a helper or to a partial. The helper
    would build and return a single string with HTML so that you can use
    it like this

    <%= role_list_header %>

    yes, but which helper file exactly? All that I have read about helpers
    indicates that they are tied to a specific controller by name. I tried
    adding a dummy method to a file called lib/application_helper.rb but
    when I called the method from a view I got a missing method error.

    James B. wrote:

    I figured out what I was doing wrong in application_helper.rb. It really
    helps if you put:

    module ApplicationHelper

    end

    around your code. double sigh.

    On Fri, May 2, 2008 at 11:17 PM, James B.
    [email protected] wrote:

    James B. wrote:

    I figured out what I was doing wrong in application_helper.rb. It really
    helps if you put:

    module ApplicationHelper

    end

    around your code. double sigh.

    Careful, you don’t need that file in lib, see the path in my previous
    post.

    On Sat, May 3, 2008 at 12:05 AM, James B.
    [email protected] wrote:

    Xavier N. wrote:

    Careful, you don’t need that file in lib, see the path in my previous
    post.

    What are the implications of each. Why one place rather than the other?

    Because app/helpers is the directory where helpers are expected to be
    by convention. Note that application_helper.rb is generated there by
    the rails command, and it already contains a module ApplicationHelper.