How much view logic in controller?

I’m working on my first AJAX-heavy app… it’s for an intranet app and
is intended to feel a bit like a desktop app… in other words, there is
a lot of asynchronous updating going on and very few “page views”.

I’m finding that I have a lot of very specific actions for remote calls
(things like “refresh_asset_list”), many of which have a render :update
calls to update elements on the page whose names are hard-coded.

This makes me feel dirty! Is it proper for the controller to have–and
rely on–such specific knowledge of the view? The only alternative that
I thought of was for the view to pass the name of an RJS template for
rendering at the end of the action.

Dave S. wrote:

I’m working on my first AJAX-heavy app… it’s for an intranet app and
is intended to feel a bit like a desktop app… in other words, there is
a lot of asynchronous updating going on and very few “page views”.

I’m finding that I have a lot of very specific actions for remote calls
(things like “refresh_asset_list”), many of which have a render :update
calls to update elements on the page whose names are hard-coded.

This makes me feel dirty! Is it proper for the controller to have–and
rely on–such specific knowledge of the view? The only alternative that
I thought of was for the view to pass the name of an RJS template for
rendering at the end of the action.

Architecture can be a weighty topic to discuss on a forum but I’ll try
and at least hit the tip of the iceberg and be as concise as possible.

If what you are referring to as ‘specific knowledge of the view’ is just
really a process of retrieving, massaging and preparing the data into
objects FOR the views to display, then you are doing it right. If
you’re controller determines font size, color and alignment, then you
aren’t.

Inversely…

If your VIEW is pre-determining what should be rendered after the next
click / asynchronous update is done, then you are mixing the purposes of
the Model / View and Controller in an MVC architectured system. In this
case your model is literally controlling your controller.

Look at it this way: the controller should be used to tie the info the
view needs (not it’s markup) to the source of the data (through models)
and WHAT should be rendered after the data is processed. (AKA Business
Logic / Rules).

You can almost make an argument of using 1 method in a controller to
handle 1 use case (or story if using scrum / XP) for your system. Your
controller would get data (using a model) and could potentially perform
an infinite number of actions based on the data retrieved and the
results of your rules. Your controller would then have this info
packaged into objects (as I mentioned) and then let the view determine
it’s orientation, color, weight on the page for the user.

Since your controller maps a use case it SHOULD determine (even if you
have to hard code it) where it will render the info. Having something
too dynamic and generic can lead to spaghetti code and cause a nightmare
if you ever need to change the ‘flow’ of your application.

I don’t remember where I read this but I use it as my mantra (and Rails
helps me do this easily)… “I never consider elegance when implementing
a solution but in the end, if my solution is not elegant, it’s wrong”.

I would think (without looking at your code and just basing it on my
experiences and ‘gut feeling’) having something too dynamic like you are
contemplating, won’t be easy and elegant to maintain.

So let’s just make a blanket statement of the three tiers in an MCV
system.

  • Model handles the state of the information and it’s source
    Controller handles the job of what models to use based on business rules
    and your systems internal logic
  • The Views only shows the information it’s been sent.

I would be happy to expand on this in a more detailed way (pros and cons
with examples) if you’d like.

I hope this, at the least, gets you started.

Jean N. wrote:

Dave S. wrote:

So let’s just make a blanket statement of the three tiers in an MCV
system.

MCV == MVC. :slight_smile:

Sorry about that.

OK, so I’ll avoid any attempts to make it too flexible… I suppose
that’s the framework’s job, and by the time we use the framework we
assume that we’ve had enough abstraction already.

My problem lies with the RJS rendering… it’s in the nature of the
render :update call itself…

render :update do |page|
page.replace_html ‘someElementName’, blah #<-- This one
doesn’t bother me
page.visual_effect :toggle_blind, ‘someElementName’ #<-- This one is
iffy
page.visual_effect :fade, ‘someOtherElementName’ #<-- Again,
iffy…
end

All of this RJS stuff–especially once it starts to get into some of the
effect–seems to be stepping on the view’s toes. It doesn’t seem like
the controller should have so much control over the appearance of the
page. It DOESN’T, however, get into style issues aside from the ones
that are implied by the use of the effects.

That’s why I was thinking that the controller might accept an RJS file
from the view, but that would eliminate the ability to conditionally
render RJS depending on the outcome of an action.

Sure it’s “doing” the same thing, but the logic is removed from the
controller into the view piece of the framework.

So, if I move all of those render :update calls into RJS templates, it
does EXACTLY the same thing, but keeps the controller’s hands clean?
It’s really more of an organizational change–the controller still
determines which RJS, etc., gets rendered, but it feels more “correct”
to me… I think it fixes what has been bugging me. I just don’t want to
EVER see a view element’s name in the controller if possible (aside fro
POST parameters, of course).

Cool… thanks.

Dave S. wrote:

OK, so I’ll avoid any attempts to make it too flexible… I suppose
that’s the framework’s job, and by the time we use the framework we
assume that we’ve had enough abstraction already.

My problem lies with the RJS rendering… it’s in the nature of the
render :update call itself…

render :update do |page|
page.replace_html ‘someElementName’, blah #<-- This one
doesn’t bother me
page.visual_effect :toggle_blind, ‘someElementName’ #<-- This one is
iffy
page.visual_effect :fade, ‘someOtherElementName’ #<-- Again,
iffy…
end

All of this RJS stuff–especially once it starts to get into some of the
effect–seems to be stepping on the view’s toes. It doesn’t seem like
the controller should have so much control over the appearance of the
page. It DOESN’T, however, get into style issues aside from the ones
that are implied by the use of the effects.

That’s why I was thinking that the controller might accept an RJS file
from the view, but that would eliminate the ability to conditionally
render RJS depending on the outcome of an action.

Although this is not considered wrong in the Rails world, from a design
point of view I’m totally against it.

I would be hesitant to put this directly inside the controller. Sure if
you only have 1 set / grouping of Ajax visuals to render you’re okay,
but what if you need to take conditional action.

I’d just remove it from the controller and slap it into a _update.rjs
template and call the render method passing it the file / action /
template symbol.

like:

def update
case i
when “foo”
# does the replace / visual effects toggle_blind and fade
mentioned above
render :template => ‘/path/to/template/’
when “bar”
# displays a second set of information not seen in “foo” plus uses
the highlight / fade visual
render :partial => ‘foo_template’
when “baz”
# Need to process this request further and use a whole new set of
layouts due to some obscure business rule.
render :action => :some_other_action, :layout =>
‘change_to_this_layout’
end
end

Sure it’s “doing” the same thing, but the logic is removed from the
controller into the view piece of the framework.

Then you’re controller can conditionally call other templates based on
need. Change in the view? No coding other than changing the .rjs file,
exactly where you want this change to be.

Note: You I used an example of template, action and partial just to show
the options you have. You can use all partials in your conditions if you
like.

Talk to you son.