What's New in Edge Rails: An Explicit Locals Hash

Posted by ryan
at 12:23 PM on Tuesday, September 05, 2006

In what is amounting to my most useless post yet – this feature has been reverted according to Bob .

With Rails components being shunned throughout the Rails world we are often left to use a set of view partials to abstract out commonly used display functionality. Sometimes this necessitates the use of variables (called ‘locals’) that may or may not be relevant in all view scenarios. For instance, if I have a partial that I use to display form text fields there may be a size parameter I want to pass in to limit the field’s size:


# my_form.rhtml
<%= render :partial => 'text_field', :locals => {:size => 5} %>

# _text_field.rhtml
<input type="text" size="<%= size %>" />

If I want the size parameter to be optional however, I could try to do this with a default value of 5:


# _text_field.rhtml
<input type="text" size="<%= size ? size : "5" %>" />

However, this fails if no size parameter is passed to the partial as size hasn’t been defined yet. With this update, however, you can query an explicit locals hash to determine the existance of a local variable:


# _text_field.rhtml
<input type="text" size="<%= locals[:size] ? size : "5" %>" />

Not a huge update, but if you’re using partials extensively (which I suspect most are) you’ve no doubt run into this issue.

And as Bojan has pointed out you could also use the nifty defined? method


# _text_field.rhtml
<input type="text" size="<%= defined?(size) ? size : "5" %>" />

tags: ,

Comments

Leave a response

  1. BojanSeptember 07, 2006 @ 06:07 AM
    That's good news :) Writing
    <input size="<%= locals[:size] || " type="text" 5>
    
    is much easier then:
    <input size="<%= defined?(size) ? size : " type="text" 5>
    
  2. Ryan MulliganSeptember 07, 2006 @ 06:29 AM
    I would say that you could always do... size ||= '5" and you'd have the same effect without doing anything crazy.
  3. Bob SilvaSeptember 07, 2006 @ 06:39 AM
    Hi Ryan, This feature got reverted due to conflicts with the Builder. I'm hoping they find some time to revisit it soon. Bob
  4. Aaron BlohowiakSeptember 07, 2006 @ 09:04 AM
    When I have a partial that takes optional params, i pass in a hash. in my partial, i have a default hash with all of the params. then, i make a "values" hash by using ruby's merge function. For different ways of doing this, see http://www.bigbold.com/snippets/posts/show/2329 And the ruby doc is at http://www.ruby-doc.org/core-1.9/classes/Hash.src/M002457.html
  5. Lee HericksSeptember 07, 2006 @ 01:25 PM
    I agree with the first comment. It is simpler to take advantage of Ruby's ability to evaluate things down to true or false. If the local doesn't exist, then the default value will be used without an additional assignment from "||=". It is costly to instantiate objects.
  6. jasonSeptember 07, 2006 @ 03:23 PM
    Wouldn't it be usefull to declare all variables at the top of the partial? If the partial is intended for reuse, then I'd prefer to work out all my variables at the top, so its ultra clear what the partial expects. So this: <input size="<%= locals[:size] || " type="text" 5> Will always be this: <input size="<%=size%>" type="text" /> Because size has been declared at the top :)
  7. jasonSeptember 07, 2006 @ 03:27 PM
    Sorry my tags got swollowed by this form. What I was showing was that you should never (in my opinion) resolve the value of size within the input tag... the input tag should just use size as is, and declare size at the top of your file. This makes the partial more re-usable, easier to understand, and cleaner
  8. PeterSeptember 08, 2006 @ 12:03 AM
    Using this method, won't you end up with an empty size attribute if it has no value? I would prefer to have no attribute at all to make my HTML as small as possible.
  9. jasonSeptember 10, 2006 @ 08:45 PM
    Peter: You could put the declaration inside a string: size ||= "5" sizeParam = "size='#{size}'" ... <input type="text"><%=sizeParam%> >
  10. jasonSeptember 10, 2006 @ 08:51 PM
    ugh, i the way this text box doesnt escape html kinda sucks im just a slow learner, i suppose
  11. Alex WayneOctober 05, 2006 @ 02:16 PM
    I think jason means something like this: http://pastie.caboo.se/16254 Which is my current method of making sure that local variables are declared. Otherwise simply testing a variable for existence like: foo(bar) if some_var will blow up with a method missing error since some_var doesn't exist. It isn't even nil. I really liked this change, and to me it seems much more natural to have a hash of passed values, rather than a handful of local variables created with a string eval. I hope it comes back.
  12. sergeyDecember 15, 2006 @ 05:06 AM
    It's strange, but 'locals' variable is not discarded in edge? so locals[:size] not woks more