I always found one thing severely missing from Rails' partials: an
equally easy "Rails" way to not just share view templates easily even
across controllers, but also have certain controller code associated
with a partial needed to get certain variables for the partial. Right
now there is no code associated with a partial, it's just a view
template. That's bad sometimes, because not always is the code for
setting variables used in the template different between usages of
that one template.
Right now I have to duplicate the code though, and especially when
using a template from a different controller this is very awkward,
since I cannot just create a new local method for the shared code. I'd
have to put it in ApplicationController, for example, but it really
belongs into the controller "owning" the particular partial.
One usage example which I'm using right now:
Instead of a different page for the shopping cart, adding addresses
and performing payment I want ONE page with all of them, saving the
user clicks and letting them see the entire (very short) process at
once on a long scroll. This has been proven to lead to a better user
experience compared to splitting (a very simple process in my case)
into lots of tiny pieces (but even if not, it's what I want).
As you can see I'd have to duplicate code from shopping_carts/index,
addresses/index, orders/new for that page, even though all those
pieces of code clearly logically belong into their respective
controllers. If I could have partials that automatically run a local
"per partial" method of their owning controller when called to
render...
PS: By the way, one thing I could think of (of course, since it's
obvious) is to write (a) module(s) in lib/with the common code for the
partial(s). However, since the partial already belongs to a view and
therefore to a certain fixed controller, I think it would make much
more sense to either A) also require that view partials are
independent of a controller, or B) that common code belongs into that
controller. Otherwise it's a double standard.
I do see the difficulty that the webserver created an object of the
currently active controller, but it would have to create a new one for
each controller. Or I could use class methods - but in class methods I
don't have access to the calling instances variables (and setting any
does not work either, but that's the whole point, to set variables for
the views - of course functional programmers will cringe - side effect
heavy code... but that's how we do it in non-functional programming
all the time). Well, one can solve it by handing that class method as
a single parameter "self" when calling it, and access and set
variables using ("this" is the parameter in the method that gets
"self" from the caller) this.variable (if already set) and
this.instance_variable_set("@variable", value) to set new instance
variables.
However, that just doesn't look right.
I always found one thing severely missing from Rails' partials: an
equally easy "Rails" way to not just share view templates easily even
across controllers, but also have certain controller code associated
with a partial needed to get certain variables for the partial. Right
now there is no code associated with a partial, it's just a view
template. That's bad sometimes, because not always is the code for
setting variables used in the template different between usages of
that one template.
Right now I have to duplicate the code though, and especially when
using a template from a different controller this is very awkward,
since I cannot just create a new local method for the shared code. I'd
have to put it in ApplicationController, for example, but it really
belongs into the controller "owning" the particular partial.
One usage example which I'm using right now:
Instead of a different page for the shopping cart, adding addresses
and performing payment I want ONE page with all of them, saving the
user clicks and letting them see the entire (very short) process at
once on a long scroll. This has been proven to lead to a better user
experience compared to splitting (a very simple process in my case)
into lots of tiny pieces (but even if not, it's what I want).
As you can see I'd have to duplicate code from shopping_carts/index,
addresses/index, orders/new for that page, even though all those
pieces of code clearly logically belong into their respective
controllers. If I could have partials that automatically run a local
"per partial" method of their owning controller when called to
render...
How do YOU guys solve such a situation?
I'd say that if the page uses several resources on a view, they all
belong to that controller, even if they "have the name" of a different
one. In any case, if you don't want to pollute ApplicationController
with methods to load code from other places and you need to reuse the
logic to load certain resources, write some modules and throw them in
lib. It's all just ruby, in the end
module ShoppingCartData
def load_addresses
@addresses = current_user.addresses.all
end
...
end
class AddressesController < ApplicationController
include ShoppingCartData
def index
load_addresses
end
end
class ShoppingCartsController < ApplicationController
include ShoppingCartData
one pattern I have found useful to remove logic from partials is to
wrap the render call in a helper method. So there is a place to setup
some instance variables or provide default values etc. Of course this
is not a place to put controller logic. But using sufficiently rich
models with scopes and associations my controllers turn out to be
boilerplate most of the time anyway.