optional local variables in rails partial templates: how do I get out of the (defined? foo) mess?

前端 未结 12 1977
没有蜡笔的小新
没有蜡笔的小新 2020-12-04 04:41

I\'ve been a bad kid and used the following syntax in my partial templates to set default values for local variables if a value wasn\'t explicitly defined in the :locals has

相关标签:
12条回答
  • 2020-12-04 05:17

    Ruby 2.5

    Erb

    It's possible, but you must to declare your default values in the scope.

    VARIABLE the word for replacement.

    # index.html.erb
    ...
    <%= render 'some_content', VARIABLE: false %>
    ...
    
    # _some_content.html.erb
    ...
    <% VARIABLE = true if local_assigns[:VARIABLE].nil? %>
    <% if VARIABLE %>
        <h1>Do you see me?</h1>
    <% end %>
    ...
    
    0 讨论(0)
  • 2020-12-04 05:18

    A helper can be created to look like this:

    somearg = opt(:somearg) { :defaultvalue }
    

    Implemented like:

    module OptHelper
      def opt(name, &block)
        was_assigned, value = eval(
          "[ local_assigns.has_key?(:#{name}), local_assigns[:#{name}] ]", 
          block.binding)
        if was_assigned
          value
        else
          yield
        end
      end
    end
    

    See my blog for details on how and why.

    Note that this solution does allow you to pass nil or false as the value without it being overridden.

    0 讨论(0)
  • 2020-12-04 05:19

    I think this should be repeated here (from http://api.rubyonrails.org/classes/ActionView/Base.html):

    If you need to find out whether a certain local variable has been assigned a value in a particular render call, you need to use the following pattern:

    <% if local_assigns.has_key? :headline %>
      Headline: <%= headline %>
    <% end %>
    

    Testing using defined? headline will not work. This is an implementation restriction.

    0 讨论(0)
  • 2020-12-04 05:21

    Since local_assigns is a hash, you could also use fetch with the optional default_value.

    local_assigns.fetch :foo, default_value
    

    This will return default_value if foo wasn't set.

    WARNING:

    Be careful with local_assigns.fetch :foo, default_value when default_value is a method, as it will be called anyway in order to pass its result to fetch.

    If your default_value is a method, you can wrap it in a block: local_assigns.fetch(:foo) { default_value } to prevent its call when it's not needed.

    0 讨论(0)
  • 2020-12-04 05:25

    More intuitive and compact:

    <% some_local = default_value unless local_assigns[:some_local] %>

    0 讨论(0)
  • 2020-12-04 05:34

    I know it's an old thread but here's my small contribution: i would use local_assigns[:foo].presence in a conditional inside the partial. Then i set foo only when needed in the render call:

    <%= render 'path/to/my_partial', always_present_local_var: "bar", foo: "baz" %>
    

    Have a look at te official Rails guide here. Valid from RoR 3.1.0.

    0 讨论(0)
提交回复
热议问题