I’m toying with the idea of replacing the current code-overloading
scheme in Engines (where it merges code from multiple
controllers/helpers). What I might do instead is just have people use
normal inheritance/module inclusion. So if you wanted to change a
method in the UserController of the LoginEngine, for example, instead
of just creating your own /app/controllers/user_controller.rb with the
new method, you might actually create that controller as a subclass:
class UserController < LoginEngine::UserController
def protect
# your overloaded method
end
end
The advantage of this is that it means I don’t need to search load
paths or modify any require strings. It also makes it a bit clearer to
the application developer that their controller is part of a grander
piece of code (currently there’s no explicit relationship between
overriding controllers and engine controllers).
An alternative scheme would be to have the controller code in a module
with a stub controller in the engine, which wouldn’t be loaded if a
similar controller existed in the main app. This would be identical to
the way the user model object is defined and overridden currently.
Doing something like this may solve the current problem of having to
get REALLY freaky with loading/requiring code (see Ticket #53 for
instance) annd be more future-proof, but also might introduce new
issues.
Anyway - does anyone have any thoughts? The floor is open…
I like the idea of avoiding as much “black magic” as possible. Which
to many, the dynamic runtime classpath/loading issues seem to be.
I’m just trying to think how you would find the all the overloaded
classes and make sure they are all used correctly. For example, the
login and user engines.
Right now the user engine would inherit from the login engine, fine,
but what if someone had an additional engine that modified the login
engine with additional methods (overriding existing methods would be
messy in any case), how would you know where to find the new
extensions to the login engine and not use the user engine controller
instead.
I don’t know if I’m making any sense here, but I hope you get the gist
of it.
I have some other thoughts, but am trying to find a way to formulate
the wording so it makes some sense
I think this is a good idea because
1 - makes the code more readable
2 - avoids to create an heavy and dangerous legacy for future
development of the engines concept
3 - does not really have a dark side (Not that I can see. Can anybody
mention one?)
In general I think that the philosophy behind the engines should be to
create pieces of really reusable SW more than go on the “black magic”
path, as Nick points out. In this sense I would even suggest that we
should get in the habit to dedicate a namespace to our engines.
If, for instance, I write a todo_list_engine, I probably want my
contoller to be called TodoList::ItemController, otherwise whoever wants
to use my engine has to make sure that there are no other ItemController
in his/her application.
Would this make your work with the engines plugin more complicated? What
is your opinion?
Rails at the moment is not really supporting (not easily at least)
namespace usage on the model side. This is, in my opinion, the major
problem to be faced for the estabilishment of a sound engine concept.
I would prefer the inclusion approach, as used for models currently. I
don’t see any reasons for using inheritance in this case.
Regarding per-engine namespaces, I had the same feeling too. But. First,
nothing prevents from making a namespace manually, by moving your
controllers into a subfolder. Second, in the cases like Login/User
engine, it is not clear how these namespaces should be related. (Will
UserEngine get it’s own namespace, which would include everything
contained in the LoginEngine namespace?)
This way, a careful study is required. However I agree that namespaces
are very important for establishing wide usage of engines.
I’m toying with the idea of replacing the current code-overloading
scheme in Engines (where it merges code from multiple
controllers/helpers). What I might do instead is just have people use
normal inheritance/module inclusion. So if you wanted to change a
method in the UserController of the LoginEngine, for example, instead
of just creating your own /app/controllers/user_controller.rb with the
new method, you might actually create that controller as a subclass:
class UserController < LoginEngine::UserController
def protect
# your overloaded method
end
end
I am just getting started learning Ruby (I hardly know much at all–and
that goes for Rails and the Engines, too), but as an old C++ guy, I
remember with horror the problems we used to have when ‘upgrading’ to a
new version of a C++ framework, where we inherit from the provided
functionality of an older version of the framework.
Similarly, I don’t know if a late-binding script language like Ruby has
similar problems or if your current code-overloading scheme solves it or
has the same problem, but if I were you, I’d google a few keywords like
“framework class brittleness upgrade problems C++” etc., you get the
idea. Maybe even try Borland OWL or Microsoft’s windowing framework for
C++ (I can’t recall the name of it now), then head over to the Ruby
language forums to ask the gurus there about class design and
“versioning over time” of Ruby classes and see what they say.
HTH,
Brad
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.