Controller Blocks vs Classes

87 views
Skip to first unread message

activestylus

unread,
Mar 7, 2011, 4:32:58 PM3/7/11
to pad...@googlegroups.com
I'm curious about the choice of blocks for building controllers as opposed to classes.

Is it a performance thing? .. a built-in constraint against non-explicit code?

Obviously what I miss most is the inheritance. On especially large apps it can be very tedious to duplicate so much behavior. Feeling the pain right now :/

Is anyone out there working on a large-ish app (40+ models)?

How are you writing your controller code?

I need some inspiration

activestylus

unread,
Jan 28, 2012, 1:13:34 PM1/28/12
to pad...@googlegroups.com
1 year later and I'm still curious about this. I had a pretty large project  but moved it to Rails because I found the controllers unmanageable. I do have a medium sized app and it feels (to me) that this is the size Padrino is best suited for, the controller layer has been the only bottleneck/pain-point for me. Definitely prefer classes to blocks to keep things nice and DRY. I wish there was a padrino gem to swap out one for the other

Eleo

unread,
Jan 31, 2012, 9:17:04 AM1/31/12
to pad...@googlegroups.com
I think the short answer is that Padrino does it because Sinatra does it.

Personally, I prefer class-based controllers, as per Rails (blegh) or Merb.  However if Padrino went this route, could it still use Sinatra's approach to controllers under the covers?

Object-oriented is also generally easier to test.  If my controller is a class and my actions are instance methods, then there's a lot more control there.

On the other hand, the bare-bones-ness (yes I just made that up) of testing Padrino's controllers merely with Rack-Test has forced me to re-evaluate the complexity of my controllers as well as my tests.  My tests on controllers tend to be really simple.  I test for basic things like if a request can be made for a certain content type, if the request results in the correct content type, or returns an HTTP status code.  Unlike Rails I can't test for the assignment of variables -- which is fine.  I think that ties the tests too much to their implementation.  Integration tests ultimately ensure everything is copacetic in my app; which variables are or aren't being set is irrelevant.  This keeps my tests easier to maintain.

Still, there's an argument for class-based controllers.  You'd have to get a response from someone on the core team about that.  I've probably dug more into the Padrino internals than most, but there are aspects of it that still elude me.

activestylus

unread,
Feb 2, 2012, 5:40:51 AM2/2/12
to pad...@googlegroups.com
Thanks for the reply Eleo - you've given me some food for thought. 

I will keep bumping this up in hopes that one of the code devs will chime in.

Florian Gilcher

unread,
Feb 2, 2012, 5:57:08 AM2/2/12
to pad...@googlegroups.com

On Feb 2, 2012, at 11:40 AM, activestylus wrote:

> Thanks for the reply Eleo - you've given me some food for thought.
>
> I will keep bumping this up in hopes that one of the code devs will chime in.

Yep, keep bumping this. I hope that I finally find the time to write my perspective
on my train ride home today.

Nathan

unread,
Feb 2, 2012, 6:12:46 AM2/2/12
to pad...@googlegroups.com
Would be interested to hear your perspective as well. I think Eleo hit on it that in the early days we went with a routing approach that was a minor superset of Sinatra. Then Joshua Hull introduced usher (and then http_router) which expanded the router a lot, gave us new features but fundamentally was very reminiscent of the original sinatra routing style. I don't think we really considered much moving to an class-based routing system because I think it felt a bit that it might be straying too far from the original sinatra style. 

No matter what we end up doing, Padrino should be a superset of sinatra. That means adding routes to app.rb and using that style should always work as expected no matter what. But that doesn't mean that a class-based approach couldn't work as well. I do agree class-based can be easier to test, fits well with the paradigms of ruby and through inheritance and so forth does allow for a bit more power. The other question though is if supporting both these syntaxes and concepts should be supported in core. How would classes and methods work in relation to the sinatra routing style? I would want whatever we do to fit the sinatra style and philosophy.

Curious what your proposed class-based controller syntax would look like?

Florian Gilcher

unread,
Feb 2, 2012, 12:47:58 PM2/2/12
to pad...@googlegroups.com
Finally.

My opinion on this is: The word "controller" is a lie and should be replaced by "namespace", because thats what padrino controllers actually are: fancy definition blocks that have some context, but ultimately compile down to routes. As such, they don't really merit the "class approach". If you need a class behind your routes, implement one. Padrino doesn't really have 'controllers'. The trap here is that people treat Padrino applications like Rails applications: there is only one app directory, sometimes there are two (app and admin). What you end up is a huge number of files in app/controllers, a lot of special casing in app.rb and quite a few helpers with specialized functionality in app/helpers and a bunch of models with no inner order in models. Yet, they miss the crucial part: Padrino is perfectly capable to mount multiple applications together and let them act as one. So the method of separation is "multiple apps", not "multiple controllers".

What you should do, is the following:

* Everything that has widely divergent use-cases, naming schemes or models should land in its own app (e.g. Frontend, Api, Admin, Dashboard, UploadLocation). If you do this right, you can develop with only one app directory open at all times. Use the fact that all applications can have different settings. Applications can depend on others, but only in one direction. If applications show a cyclic dependency, move them back into one.
* If 2 apps share helpers or code, implement them as Sinatra plugins and put them in "lib" instead. This ensures that code is never loaded twice. Register them in app.rb anywhere you please. The initalizers that Padrino generates (SassInitializer etc.) are a good example of how small they can be. Make this a habit.
- Read about Sinatra::Application.helpers and Sinatra::Application.register
* Shared models always go to /models
* Try to break out of your controller code as fast as possible and delegate to a library (thats actually true for Rails as well). This is similar to GUI programming: you usually don't implement what a click does in the click handler. Everything concerned to produce a HTTP response (status, redirect, etc.) does belong in the app though.
* If you are tired of having a huge "register" block on top of all your app.rb files, build your own application class on top of Padrino::Application.
* Learn about Rack, Sinatra::Application.use and Padrino.use. They allow fine-grained control of the middleware-stack and are key to doing most of the stuff you would do in before-filter instead. Having multiple applications allows you to differ on the Rack middleware stack without playing with to many conditionals.

Okay, end of the train ride, please ask any questions that come up.

Regards,
Florian

Nathan Esquenazi

unread,
Feb 2, 2012, 2:26:14 PM2/2/12
to pad...@googlegroups.com
Great feedback. With Padrino, I have many projects now of various sizes and through the use of multiple subapps, middlewares, helpers, using PORO (plain old ruby objects), etc as you mentioned above, you can generally solve the complex app and 'controller' issues in a different way. And your right, "controller" in Padrino is a bit of a misnomer, namespace might be more appropriate nomenclature.

activestylus

unread,
Apr 28, 2012, 10:06:23 AM4/28/12
to pad...@googlegroups.com
I'm not sure how I missed this excellent reply, but thanks for taking the time to write it!

One of the things you said intrigued me "build your own application class on top of Padrino::Application"

I have a rough idea of how to do this, but I'm curious what the best practice is. Where would I save this application class?




Florian Gilcher

unread,
Apr 28, 2012, 12:36:25 PM4/28/12
to pad...@googlegroups.com
Either your own library (gem), if your set of helpers and stuff merits its own set of test and stuff or just put it in lib/. I would probably develop in lib as long as its moving fast and then move it to a library that is included using git/bundler.
Reply all
Reply to author
Forward
0 new messages