[LRUG] Proffer and introducing constraints to Rails

mudge mudge at mudge.name
Mon Apr 2 13:50:47 PDT 2012


What with Avdi Grimm's "Objects on Rails" and the recent LRUG
discussions about object-oriented design and the importance of message
passing, I wanted to explore making view rendering a little less
implicit.

If you look at how the Django Tutorial describes template rendering in
https://docs.djangoproject.com/en/1.4/intro/tutorial03/#a-shortcut-render-to-response,
a "context" (viz. state to pass to the template) is an explicit second
argument to `render_to_response`. Rails' equivalent -- `render` --
makes this slightly more "magic" (for want of a better word) by making
it possible to skip this argument or even the method call altogether.
By doing this, it is unarguably more convenient (as Andy states) but
it also obscures what the framework is doing.

Fundamentally, Proffer only does two things: stops instance variables
being passed to the view context and provides an interface that
actually just defines a hash that is passed to `render` as the
`:locals` option.

In formulating this argument, I wonder if we shouldn't have ditched
the `proffer` API altogether and just stated that one must use
`helper_method` and something like `render :index, :locals => { ... }`
explicitly. In this way, it might be clearer that controllers and
views are not some special case but yet more method calls and
collaborations between objects that can be test-driven or interrogated
in the usual way.

I'll be at LRUG tomorrow (and I may even pluck up the courage to
announce who I am when Murray opens up the floor at the start) as I
believe James will so feel free to pester us then.

Even if you don't agree with this particular constraint, I am
genuinely interested to hear what other helper gems we could create to
encourage better practices (e.g. Tom Stuart's suggestion to remove
development mode in order to demonstrate testing as the primary method
of verifying code correctness during the Fishbowl last month).

On Mon, Apr 2, 2012 at 8:12 PM, Paul Doerwald <paul at liquidmedia.ca> wrote:
> I've been thinking about the Proffer gem all day since I read about it this
> morning. There was something I liked about, and yet was simultaneously
> bothered by, and I think thanks to Andrew's message below been able to
> figure out what it is.
>
> What I like about Proffer is that it enables a stronger separation of
> concerns. Initially liked the idea of having to manually declare the
> variables that the view would have access to. It feels a bit like
> programming and less like magic. I personally don't mind a few extra
> keystrokes if it makes the code more clear and/or more secure.
>
> Upon further consideration, I feel that Proffer doesn't add very much.
> Essentially, in the context of a controller, simply declaring an @variable
> can essentially be considered to be proffering a variable to the view.
> Proffer does the same thing but just with a different syntax. I don't mind
> the syntax and would be happy to use Proffer instead. The only advantage
> Proffer adds in this context is that the view's access to variables is
> limited to those that are proffered rather than every instance variable
> available to the controller.
>
> As I considered this "advantage" I decided that the risk of the view having
> access to non-proffered variables (that is, every @variable) is very low,
> because the developer that created the controller action is probably the
> same developer that created the view. There was no security risk that needed
> to be averted. Making an @filesystem variable available to every view will
> never be a risk without the programmer doing something dangerous with that
> variable.
>
> That said, to the authors (James & Paul), I don't mean to be discouraging. I
> think you explored a really cool idea and I like *why* you're thinking along
> these lines. It adds some rigour to Rails which wasn't there before. More
> thinking like this would have prevented the major Github security issue of a
> few weeks ago. There's nothing wrong with having to declare every variable
> that your model has; it helps the programmer protect from him/herself. In
> the same way, Proffer is the more "correct" way to do Rails.
>
> But Andrew's point "with Rails it's usually better to go with the flow
> unless there's a good reason otherwise" IMO applies here. Rails approach
> isn't great, but it's not bad enough to replace
>
> Paul.
>
> --
> Paul Doerwald
> Chancellor
> Liquid Media Inc.
> 902-412-2492
>
> On Monday, 2 April, 2012 at 3:55 PM, Andrew Stewart wrote:
>
>
> On 2 Apr 2012, at 17:05, James Hunt wrote:
>
> How much more convenient is it though? How much time do you really save by
> having instance variables by default?
>
>
> Compared to the Java way, which is where I came from when I switched to
> Rails, using `@post` in a view is far more convenient than `((Post)
> request.getParameter("post"))` (if I recall my Java from 7 years ago
> correctly).
>
> Compared to Proffer, I think this:
>
> class PostsController < ApplicationController
> def new
> @post = Post.new
> end
> end
>
> <%= form_for(@post) do |f| %>
> ...
> <% end %>
>
> -- is more convenient than this:
>
> class PostsController < ApplicationController
> include Proffer
> def new
> proffer :post => Post.new
> end
> end
>
> <%= form_for(post) do |f| %>
> ...
> <% end %>
>
> I think it consistently saves a little bit of time.
>
> It's interesting to think about this the other way: if Rails had never
> exposed instance variables by default, would you even miss it? Would you
> have written a gem to add the functionality? How would you justify it?
>
>
> I didn't have it before so I wouldn't have been able to miss it. However if
> it vanished now I would write a gem to replace it...unless it seemed I was
> in a tiny minority; with Rails it's usually better to go with the flow
> unless there's a good reason otherwise.
>
> In the scheme of all the things you have to do to get a Rails app working,
> not having instance variables in views seems like a really small thing.
>
>
> True, but a lot of Rails' productivity boost comes from the aggregation of
> many little time-savers.
>
> And if you were reaaaaallly desperate, you could do:
>
> <% @post = post %>
>
> at the top of your view and you're back in business! The only difference
> here is that before you do something like the above, you have to actually
> think about what you're doing and why before you do it. It's a convention:
> break it if you want, but know why you're doing it and what it may cost you
> later on.
>
>
> For me, using an instance variable instead of a plain local variable is a
> fine convention. If I want to share state with a view, I use an instance
> variable; if I don't want to share state, I use a local variable.
>
> Cheers,
> Andy
>
> _______________________________________________
> Chat mailing list
> Chat at lists.lrug.org
> http://lists.lrug.org/listinfo.cgi/chat-lrug.org
>
>
>
> _______________________________________________
> Chat mailing list
> Chat at lists.lrug.org
> http://lists.lrug.org/listinfo.cgi/chat-lrug.org
>



More information about the Chat mailing list