<!DOCTYPE html><html><head>
<style type="text/css">"body { font-family:'Helvetica'; font-size:12px"}</style>
</head>
<body><div>Finally, thank you guys. </div><div>I don't know who came up with this pattern in rails in the first place, it violates everything you ever wanted objects and instance variables to mean.</div><div><br>The erector template engine also achieved something similar. Since there you write templates as first-class ruby classes subclassing Widget. The template (controller.view_context) was only a proxy between the erector widget instance and the controller instance so it was a natural place to restrict which instance variables are delegated from the widget to the view (including all exposed from the controller). <br></div><div><br></div><div>The main difference in the API is that in erector you declare it within the widget with a class method 'needs'.</div><div><br></div><div>Your approach may be more intuitive in that it is in the controller that you set these view vars, but I think it would be more important that the local context reveals what is bound from where (declaration variables, arguments, etc). This is not trivial to implement in erb/haml since template files are not like class files, (maybe some comment structure could be used to declare locals in a template/partial preamble, but that would introduce new syntax).</div><div><br></div><div>By the way I never got why it would ever make sense to distinguish partials from non-partial templates, given that they are all just widgets, with some local vars assigned by the caller. The only difference being that unlike partials, where you pass local assignments via :locals hash, render is not explicitly called in an action most of the time.</div><div><br></div><div>Frankly, I think rails should benefit from this more explicit object-passing protocol between view and controller.</div><div><br></div><div>Proffer solves one half of it, but what if we forced the view not to abuse instance vars either by (sorry for the possibly weak pun)</div><div><br></div><div><% post = proffee :post %> </div><div><br></div><div>this has several advantages: </div><ul><li>explicitly declares that certain variables are externally bound </li><li>allows for error detection if a view needs the variable to be bound but it is not assigned in the controller instance (this i think is a problem with using instance vars in views)</li><li>allows for declaring view-defaults. this is especially useful if like me you use automatic model assigments for scaffolded crud actions (inherited_resources gem, see recent thread), then saying proffee :post => controller.resource </li><li>enables uniform handling of assigments between template/partial on one hand and controller/template on the other</li><li>agnostic to whether the templates are first class ruby classes (like in erector and others) or not</li></ul><div>what do yous think?</div><div>my 2c</div><div><br></div><div>Vik</div><div> </div><div>On Mon, 02 Apr 2012 09:59:47 +0100, James Hunt <ohthatjames@gmail.com> wrote:<br></div><br><blockquote style="margin: 0 0 0.80ex; border-left: #0000FF 2px solid; padding-left: 1ex"><div>Hello all,</div><div><br></div><div>Over the weekend, Paul Mucur (@mudge) and I knocked up a gem called Proffer:</div><div><a href="https://github.com/hudge/proffer" style="color:rgb(17,85,204)" target="_blank">https://github.com/hudge/proffer</a>.</div>
<div><br></div><div>There is more information on GitHub but the summary is that it stops Action</div><div>Controller from exposing all defined instance variables to your views by default</div><div>
and instead provides a way to explicitly declare your dependencies instead.</div><div><br></div><div>For example:</div><div><br></div><div> class PostsController < ApplicationController</div><div>
include Proffer</div><div><br></div><div> def new</div><div> proffer :post => Post.new</div><div> end</div><div> end</div><div><br></div><div>Our main rationale was to remove some of the global state that seems to pervade</div>
<div>Rails views. We want to see if forcing you to declare what information you pass</div><div>to a view would make you more mindful of the collaboration between your objects.</div><div>Would we end up with a better design if you couldn't just rely on some instance</div>
<div>variable being declared further up the chain? In particular, partials that</div><div>modify or make decisions based on data set in the controller can be especially</div><div>fiddly to maintain or reuse.</div>
<div><br></div><div><div>A lot of the talk at last month's TDD fishbowl [1] was about how to make testing</div><div>easier for beginners by improving conventions and we're using the same principle</div>
<div>here. We're attempting to guide people towards not using global state while</div><div>still not imposing a radical change in style. Avdi Grimm's recent "Objects on</div><div>Rails" takes a similar tack with his FigLeaf module [2] which makes it possible</div>
<div>to mark inherited methods as private as a way of forcing you to consider your</div><div>coupling to APIs that you may be trying to keep isolated.</div><div><br></div><div>While there are more drastic attempts at rethinking views such as Erector [3],</div>
<div>it seems like there might be opportunity for more incremental improvements to the</div><div>standard Rails approach to views.</div><div><br></div><div>As a question for the list (besides feedback on the gem which we would greatly</div>
<div>appreciate), are there any other conventions or constraints we could apply</div><div>through software to further explore Rails best practices?</div><div><br></div><div> [1]: <a href="http://skillsmatter.com/podcast/agile-testing/lrug-tdd-fishbowl" style="color:rgb(17,85,204)" target="_blank">http://skillsmatter.com/podcast/agile-testing/lrug-tdd-fishbowl</a></div>
<div> [2]: <a href="http://objectsonrails.com/#ID-5e701b05-6b1a-4cdf-9e4b-254b8f6c110d" style="color:rgb(17,85,204)" target="_blank">http://objectsonrails.com/#ID-5e701b05-6b1a-4cdf-9e4b-254b8f6c110d</a></div><div> [3]: <a href="http://erector.rubyforge.org/" style="color:rgb(17,85,204)" target="_blank">http://erector.rubyforge.org/</a></div>
<div><br></div><div>PS: Remind us to write up how this simple gem led us to contribute to RubySpec</div><div>and stay up until 3 am chasing a bug in RSpec-Rails...</div></div>
</blockquote><br><br><br></body></html>