[LRUG] Proffer and introducing constraints to Rails

Viktor Tron viktor.tron at gmail.com
Mon Apr 2 03:20:16 PDT 2012


Finally, thank you guys.
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.

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).

The main difference in the API is that in erector you declare it within  
the widget with a class method 'needs'.

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).

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.

Frankly, I think rails should benefit from this more explicit  
object-passing protocol between view and controller.

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)

<% post = proffee :post %>

this has several advantages:
explicitly declares that certain variables are externally bound
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)
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
enables uniform handling of assigments between template/partial on one  
hand and controller/template on the other
agnostic to whether the templates are first class ruby classes (like in  
erector and others) or not
what do yous think?
my 2c

Vik

On Mon, 02 Apr 2012 09:59:47 +0100, James Hunt <ohthatjames at gmail.com>  
wrote:

> Hello all,
>
> Over the weekend, Paul Mucur (@mudge) and I knocked up a gem called  
> Proffer:
> https://github.com/hudge/proffer.
>
> There is more information on GitHub but the summary is that it stops  
> Action
> Controller from exposing all defined instance variables to your views by  
> default
> and instead provides a way to explicitly declare your dependencies  
> instead.
>
> For example:
>
>  class PostsController < ApplicationController
>    include Proffer
>
>    def new
>      proffer :post => Post.new
>    end
>  end
>
> Our main rationale was to remove some of the global state that seems to  
> pervade
> Rails views. We want to see if forcing you to declare what information  
> you pass
> to a view would make you more mindful of the collaboration between your  
> objects.
> Would we end up with a better design if you couldn't just rely on some  
> instance
> variable being declared further up the chain? In particular, partials  
> that
> modify or make decisions based on data set in the controller can be  
> especially
> fiddly to maintain or reuse.
>
> A lot of the talk at last month's TDD fishbowl [1] was about how to make  
> testing
> easier for beginners by improving conventions and we're using the same  
> principle
> here. We're attempting to guide people towards not using global state  
> while
> still not imposing a radical change in style. Avdi Grimm's recent  
> "Objects on
> Rails" takes a similar tack with his FigLeaf module [2] which makes it  
> possible
> to mark inherited methods as private as a way of forcing you to consider  
> your
> coupling to APIs that you may be trying to keep isolated.
>
> While there are more drastic attempts at rethinking views such as  
> Erector [3],
> it seems like there might be opportunity for more incremental  
> improvements to the
> standard Rails approach to views.
>
> As a question for the list (besides feedback on the gem which we would  
> greatly
> appreciate), are there any other conventions or constraints we could  
> apply
> through software to further explore Rails best practices?
>
>  [1]: http://skillsmatter.com/podcast/agile-testing/lrug-tdd-fishbowl
>  [2]: http://objectsonrails.com/#ID-5e701b05-6b1a-4cdf-9e4b-254b8f6c110d
>  [3]: http://erector.rubyforge.org/
>
> PS: Remind us to write up how this simple gem led us to contribute to  
> RubySpec
> and stay up until 3 am chasing a bug in RSpec-Rails...
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lrug.org/pipermail/chat-lrug.org/attachments/20120402/237de5ab/attachment-0003.html>


More information about the Chat mailing list