Views, controller instance variables, and :needs

3 views
Skip to first unread message

Andrew Geweke

unread,
Nov 22, 2009, 3:47:12 PM11/22/09
to ere...@googlegroups.com
Hi folks --

I've been a big fan of Erector for a long time. I now have a chance to
champion its use with a commercial, large-scale Rails app (among the
top handful of largest Rails sites worldwide). We're looking at
integrating it into our existing codebase, and I've run into a couple
interesting pieces of engineering work that I wanted to share.

First: controller instance variables. ERb passes them through to the
direct view and any partials, all the way down; it also silently
ignores any extras you set. You effectively have a pool of
"globals" (views can even modify them, ick!), and if your view set is
large enough it becomes very hard to maintain. ("This action sets
@foobar, but it looks like the view doesn't use it. I want to remove
it. But maybe some partial nested six levels down uses it...maybe only
certain conditions! Uh-oh. I better leave it in place, or else spend
painful hours with grep.")

So we really want to use 'needs' to avoid this. However, our app
infrastructure, over time, has come to set many controller instance
variables across all actions -- before_filters, ApplicationController
calls, modules included into ApplicationController, and so on. (I
suspect this is prototypical of large Rails apps that have evolved
with traditional ERb views.) In our app, an "empty" action sees
several dozen controller variables. As a result, 'needs' either is
counterproductive (list several dozen in every widget...and now
several dozen are *required* everywhere) or has to be omitted,
negating one of Erector's great strengths.

What I've done is added a class method:
Erector::Widget.ignore_extra_controller_assigns=. Set this to true,
and then iff you declare a 'needs' clause in that widget, any
controller instance variables that aren't in that clause are silently
ignored, rather than causing errors. (Crucially, they aren't available
to the widget, either.) It's false by default, and inherits; the idea
is that if you need it, you set it on a Widget subclass that you use
on all your app's widgets, and it just works.

This only affects Rails widgets, nothing else, and only comes into
play when Rails renders your widget (implicit render at the end of a
controller action, or "render :template => ..", etc.) -- instantiating
the widget directly will still fail if you pass unneeded variables, as
will Erector's 'widget' helper and anything else. You can see the
diffs here:

http://github.com/ageweke/erector/commit/dd7676fbe1da4260dc35cb9a76ee97c657aef058

If folks have a different/better idea, I'm certainly all ears. But I
wanted to share this to get discussion flowing, and, if this seems
like a good idea, offer the patch for merging back upstream. I feel
like it works well and solves an existing, significant problem for
legacy Rails apps in a minimally-intrusive way -- I'm a huge Erector
fan and want to see it be able to be used everywhere. :) Let me know
what you think, and I'll work to make this the best possible!

Cheers,
Andrew

Alex Chaffee

unread,
Nov 22, 2009, 11:19:10 PM11/22/09
to age...@gmail.com, ere...@googlegroups.com
I'm not actively developing any Rails apps anymore, so I'll let one of
the others review this patch, but it looks fine to me. My only comment
is that the name is something of a mouthful; maybe make it, like,
Widget.allow_undeclared_parameters or something.

(Andrew, sorry for the moderation delay. I've been getting a lot of
spam so I have new members moderated by default. To re-enable a single
member is a 4-click process; more if you're not on the first page of
members! See http://www.webmonkey.com/blog/Google_Groups_Fail:_JQuery_Abandons_Google_Over_Spam__Interface_Problems
for more sad info.)

---
Alex Chaffee - al...@cohuman.com - http://alexch.github.com
Stalk me: http://friendfeed.com/alexch | http://twitter.com/alexch |
http://alexch.tumblr.com
> --
>
> You received this message because you are subscribed to the Google Groups "erector" group.
> To post to this group, send email to ere...@googlegroups.com.
> To unsubscribe from this group, send email to erector+u...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/erector?hl=.
>
>
Reply all
Reply to author
Forward
0 new messages