15

I was thinking that at the top of my partial I would have something like this

<% optional_width = default_value unless (defined? optional_width) 

But I've had inconsistent results with this, I'm thinking this is not a good way to do this. What is the "correct" way to do this in rails?

Janak
  • 5,025
  • 8
  • 34
  • 43
  • possible duplicate of [optional local variables in rails partial templates: how do I get out of the (defined? foo) mess?](http://stackoverflow.com/questions/2060561/optional-local-variables-in-rails-partial-templates-how-do-i-get-out-of-the-de) – Ciro Santilli OurBigBook.com Sep 30 '14 at 16:14

2 Answers2

23

Read the Passing local variables to sub templates section in the ActionView::Base docs

Basically it says you should use this pattern:

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

For you, this might translate to something like:

<div style="width: <%= local_assigns.has_key?(:optional_width) ? optional_width : 500 %>px;">
  <!-- filler -->
</div>

important!

According to the docs

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

maček
  • 76,434
  • 37
  • 167
  • 198
3

Although not exactly equivalent to your code, that's usually done with || operator.

<%  optional_width ||= default_value  %>

This is equivalent to optional_width = optional_width || default_value. Due to shot-circuit evaluation, if optional_with is "true", i.e. it's defined, and not nil, the right-hand part becomes equal to it, and default_value is not even computed. Otherwise, right-hand part would be equal to default_value. That's essentially what you want to do.

Ok, I admit that it may not work for partial's locals. The particular situation I can imagine is that if in first render call the optional_width variable was set to some value, and in the consequent call to render it is not mentioned at all while keeping its value from the first run. Can't do such a check right now, though.

P Shved
  • 96,026
  • 17
  • 121
  • 165
  • Pavel Shved, this is ordinarily fine but you need to understand the underpinnings of ActionView. As noted in the API, your solution will not work reliably. For more details, see http://api.rubyonrails.org/classes/ActionView/Base.html :) – maček Mar 05 '10 at 09:37