{"id":293402,"date":"2010-02-08T13:38:00","date_gmt":"2010-02-08T18:38:00","guid":{"rendered":"http:\/\/37signals.com\/svn\/posts\/2144-scope-a-variable-to-a-block-in-your-template-code"},"modified":"2010-02-08T13:38:00","modified_gmt":"2010-02-08T18:38:00","slug":"scope-a-variable-to-a-block-in-your-template-code","status":"publish","type":"post","link":"https:\/\/mereja.media\/index\/293402","title":{"rendered":"Scope a variable to a block in your template code"},"content":{"rendered":"<p>Sometimes you are coding a template and you need to refer to the same method chain over and over. For example, you&#8217;re coding a template that summarizes activity on recent messages. You iterate through a block of messages, and for each message you want to display some information pertaining to the last comment. You could do it like this:<\/p>\n<pre><code class=\"ruby\">&lt;div class=\"active_messages\"&gt;\n  &lt;% @active_messages.each do |message| %&gt;\n    &lt;h1&gt;&lt;%= message.title %&gt;&lt;\/h1&gt;\n    &lt;div class=\"latest_comment\"&gt;\n      &lt;div class=\"avatar\"&gt;\n        &lt;%= avatar_for(message.comments.last.creator) %&gt;\n      &lt;\/div&gt;\n      Latest comment &lt;%= time_ago_in_words(message.comments.last.created_at) %&gt; ago by &lt;%= message.comments.last.creator.full_name %&gt;\n    &lt;\/div&gt;\n  &lt;% end %&gt;\n&lt;\/div&gt;\n<\/code><\/pre>\n<p>Everything inside of div.latest_comment deals with the exact same comment, but we have to use a method chain to get the comment each time (message.comments.last).<\/p>\n<p>One solution is to set a local variable inside the iterating block with the knowledge that the variable will be reset after each iteration:<\/p>\n<pre><code class=\"ruby\">&lt;div class=\"active_messages\"&gt;\n  &lt;% @active_messages.each do |message| %&gt;\n    &lt;h1&gt;&lt;%= message.title %&gt;&lt;\/h1&gt;\n    &lt;% comment = message.comments.last %&gt;\n    &lt;div class=\"latest_comment\"&gt;\n      &lt;div class=\"avatar\"&gt;\n        &lt;%= avatar_for(comment.creator) %&gt;\n      &lt;\/div&gt;\n      Latest comment &lt;%= time_ago_in_words(comment.created_at) %&gt; ago by &lt;%= comment.creator.full_name %&gt;\n    &lt;\/div&gt;\n  &lt;% end %&gt;\n&lt;\/div&gt;\n<\/code><\/pre>\n<p>One on hand, this is better because the methods called on `comment` are easier to scan. The whole div.latest_comment is more readable without the repeated method chain. On the other hand, setting a local variable is bad style. The local variable assignment creates state without explicitly showing where that state applies. It feels a little too <span class=\"caps\">PHP<\/span> for my taste.<\/p>\n<p>A better approach is to use the `tap` method to scope a variable to a block:<\/p>\n<pre><code class=\"ruby\">&lt;div class=\"active_messages\"&gt;\n  &lt;% @active_messages.each do |message| %&gt;\n    &lt;h1&gt;&lt;%= message.title %&gt;&lt;\/h1&gt;\n    &lt;div class=\"latest_comment\"&gt;\n      &lt;% message.comments.last.tap do |comment| %&gt;\n        &lt;div class=\"avatar\"&gt;\n          &lt;%= avatar_for(comment.creator) %&gt;\n        &lt;\/div&gt;\n        Latest comment &lt;%= time_ago_in_words(comment.created_at) %&gt; ago by &lt;%= comment.creator.full_name %&gt;\n      &lt;% end %&gt;\n    &lt;\/div&gt;\n  &lt;% end %&gt;\n&lt;\/div&gt;\n<\/code><\/pre>\n<p>The `tap` block shows exactly where the scope of the assignment starts and ends. I like how the template explicitly says &#8220;now we are going to deal with a comment in the following section, and this is the comment we are working with.&#8221;<\/p>\n<p>I just hit on this pattern today while working on a feature and I think it&#8217;ll come in handy in the future.<\/p>\n<div class=\"feedflare\">\n<a href=\"http:\/\/feeds.feedburner.com\/~ff\/37signals\/beMH?a=qHhYWyYofQY:EdP_I2kXucE:yIl2AUoC8zA\"><img decoding=\"async\" src=\"http:\/\/feeds.feedburner.com\/~ff\/37signals\/beMH?d=yIl2AUoC8zA\" border=\"0\"><\/img><\/a> <a href=\"http:\/\/feeds.feedburner.com\/~ff\/37signals\/beMH?a=qHhYWyYofQY:EdP_I2kXucE:7Q72WNTAKBA\"><img decoding=\"async\" src=\"http:\/\/feeds.feedburner.com\/~ff\/37signals\/beMH?d=7Q72WNTAKBA\" border=\"0\"><\/img><\/a>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Sometimes you are coding a template and you need to refer to the same method chain over and over. For example, you&#8217;re coding a template that summarizes activity on recent messages. You iterate through a block of messages, and for each message you want to display some information pertaining to the last comment. You could [&hellip;]<\/p>\n","protected":false},"author":846,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[],"class_list":["post-293402","post","type-post","status-publish","format-standard","hentry","category-news"],"_links":{"self":[{"href":"https:\/\/mereja.media\/index\/wp-json\/wp\/v2\/posts\/293402","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mereja.media\/index\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mereja.media\/index\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mereja.media\/index\/wp-json\/wp\/v2\/users\/846"}],"replies":[{"embeddable":true,"href":"https:\/\/mereja.media\/index\/wp-json\/wp\/v2\/comments?post=293402"}],"version-history":[{"count":0,"href":"https:\/\/mereja.media\/index\/wp-json\/wp\/v2\/posts\/293402\/revisions"}],"wp:attachment":[{"href":"https:\/\/mereja.media\/index\/wp-json\/wp\/v2\/media?parent=293402"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mereja.media\/index\/wp-json\/wp\/v2\/categories?post=293402"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mereja.media\/index\/wp-json\/wp\/v2\/tags?post=293402"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}