Oh God, What Have We Done?
This was something of a response to misunderstandings about what Engines are. For more background you might want to read DHH’s first post about engines and this.
In A Nutshell:
Engines aren’t any more evil than generators are or ever were. The LoginEngine doesn’t claim or try to be a one-solution-fits-all high-level component. If anything, it’s easier to hack than the old generators. And easier to replace when you want to drop the “login scaffolding” it provides for something more comprehensively tailored to your needs.
Engines are not evil. It’s possible to write inappropriate Engines in as much as it’s possible to write inappropriate generators, or inappropriate controllers, or inappropriate Rails applications. Engines are not high level components any more than generators are. Engines are plugins which include default views. Every part of an engine is simple to override.
And now, for hopefully the last time ever:
On The Writing of Login-Type Code
Guys? Come on!! Noone is stopping you from writing your own login systems. Please do! Would you like to see an example of a login system? Why sir, here are a few! Don’t worry though, I’ll credit you with enough common sense to realise that these examples are NOT trying to do everything for everyone, and you’re not going to hurt anyone’ feelings if you don’t use them – any of them.
The One True Way
As writ on the Rails list earlier:
...one of the very problems with the One True Way of handling logins is, quite simply, that there is no wrench that fits all needs.
I’m not sure why anyone would think that any login system is the ‘one true’ login system, anymore than anyone could possibly believe that ActiveRecord is the ‘one true’ ORM system or that cookies & cream is the ‘one true’ ice-cream flavour (it’s damn good though).
The salted hash login generator wasn’t and will never be the ‘one true’ login system, but it’s been a handy workhorse to those who’ve used it. The login engine is exactly the same collection of code, but in a different distribution form, one which has specific advantages I have tried to illustrate in certain situations where a generator is less appropriate (see previous post in this thread).
It is absolutely not an attempt to standardise logins, or provide a one-solution-fits-all login system, nor does it claim to be. It won’t do everything for you. It won’t let you manage other users. It won’t gently chastise you when you give it crap data, and hand-hold you until you agree with its way of doing things. It won’t try and hide how it works either. It’s inviting you to inspect its guts and mock its flaws, and get dirty with fixing them, but equally it will keep grinning stupidly even if you turn around filled with disgust and enthusiasm as you cry “Cease! I Can Do Better Than This Junk! I Have Special Needs! My Application Is A Beautiful And Unique Snowflake!”
Absolutely Not The One True Way
You can change the behaviour of the login engine to almost the exact same degree as the original generator, so in the same respects it will get you 90% (or 80% or 75%, or 30%) of the way there; you’re just taking a different road with its own set of advantages, and obstacles. If you just want something simple, you might never need to change it. But if you want to, you can. If you need to, you can. And then if you want to throw it out in favour of your own system, tailored to your application’s specific needs, it won’t complain as you toss it into the trash. And who knows, you might’ve picked up some hints in its implementation. And you might have some hints to give back to other people.
It’s not the One True Way. It’s just an example which someone might find useful either as a working piece of their application, or as an example to help kick-start their brains into thinking about one particular way in which you might go about writing one yourself.
I agree with David in that the Rails framework should NEVER been seen to be tied to ANY type of authentication. It’s very brave of them to even consider absorbing i18n into their core. Rails is a framework for developing web applications, not for hand-holding.
All Things To Nobody
the problem with large granularity 80% solutions is that the 80% they do is never the 80% you need.
Why did nobody complain like this about the Salted Hash Login Generator (SHLG)? It does exactly the same thing, from head to toe, as the login engine. And I mean EXACTLY. In fact the login engine is even more pure, because it doesn’t tie you to a model (although it gives you a default one if you don’t need anything special), and it doesn’t include any localization at all. I’m going to freak out about this point in about 5 paragraphs time. Keep your eyes peeled.
On Helping Developers Get A Step Up To The Application They Imagine Without Hobbling Them Like In That Film, What Was It Called? Oh Yes: Misery
I really feel quite strongly about making this clear: engines are not the saviour of the lazy programmer, nor should they be seen as encouraging programmers to be lazy or to expect functionality. Engines are not a dictat from anyone about how you MUST write something, or even how is BEST to write something. The LoginEngine is not the only way to construct an authentication mechanism as an engine. Its an example. And it’s a very tightly focused one. It doesn’t do RBAC or anything else like that – it’s almost the minimum amount of code needed to produce the login behaviour that most people expect of a web application. No more.
So What Is The Point?
Plugins let use share logic to be used in the model and controller parts of our application. Engines make it a bit easier to share code from the V part of the MVC trinity, and do it in a way that minimises impact to your application without constraining your ability to change their behaviour whenever possible. Consider them as an alternative option to generators if you must. That’s basically right, except instead of producing these view files as the result of a one-time script, they’re already generated.
Rick Olson (technoweenie, plugin maestro extraordinaire) is taking an alternative approach, and providing controller macros to generate view code on the fly. That’s fine too. Some people are happier seeing the .rhtml files. Some people like the declarative approach. Either style of providing enhanced functionality could be abused. Both are valid.
High Level Components Are BAD
Nobody is disagreeing with that, but it’s wrong to tar the engines development approach just because you can write huge application chunks using them. Just because they make such a thing possible, doesn’t mean that you should, or that anyone would. I credit the community with enough sense to choose whatever works for them.
If you felt the urge, you could write a “High Level Component” as a generator. Would people use it? Maybe…. maybe not. I think natural selection will make it clear whether or not such “components” can ever really work as part of Rails development (my personal opinion, for those who are interested, is that bloated components/engines/plugins are going to bomb, hard).
But consider this – someone could write a generator that produced a whole phpnuke-style application and dumped it straight into your RAILS_ROOT/app directory. Would that be a Good Idea? Probably not. Just because the Engines plugin makes it slightly easier to commit this atrocity, does that mean that anyone would use it? Again, I hope not.
Are generators evil? Are engines evil? Are declarative interface-generating macro-based DSLs evil? Maybe, and this is going to sound like crazy beatnik talkin’ here… maybe they are both just tools which can be useful, but can also shoot yourself in the foot if you’re not careful.
The Point Where I Freak Out A Little Bit
Why did nobody work up a frenzy when generators first appeared, screaming that this new-fangled witchcraft that produces fully-functioning sub-systems – these heretical high-level components – was Black Magic Evil, the fever’d ramblings of a man-devil, hell-bent on corrupting the purity of Holy Rails? My guess is that everyone realised implicitly that nobody would be dumb enough to try and write something a generator for anything so complicated as what exists in David’s nightmares as high level components.
The only thing that’s different now is that Engines make it easier to write what previously would’ve had to be generators.
The Point Where I Calm Down
I love you guys! Group hug!
On The Strengths Of Engines Over Other Ways Of Distributing Example Application Fragments
A smart guy said of engines:
the goal of Rails is to create a world where they are neither needed or strongly desired.
Let me tell you a secret. Why does the Engines plugin exist? Because we needed to share a set of views/controllers/models amongst a group of applications. Until recently, Rails didn’t have plugins, so we made our own little version of them. Now Rails has plugins, we’ve embraced its conventions as much as possible. Unfortunately, regular plugins can’t share views. So we had to keep some of our little runtime patches, nicely isolated, and there you’ve got the Engines plugin.
Furthermore, engines are plugins, so you can update and revert them as your application needs, whilst minimising the impact on the rest of your application. ENGINES ARE PLUGINS.
Finally, engines/plugins are transparent where generators are opaque. Anyone can see how a plugin works before they let it touch their Web 3.0 masterpiece.
Is it evil to want to have a simple (simple; did I say simple?) set of views, as part of a plugin, for reuse between various applications? I don’t think so. If this was possible with the existing Rails plugin system, Engines would disappear and I’d have to do a lot less debugging at my job. Now that would be a win-win. Will people stop wanting aspects of their application programming to be done for them? You’ll be lucky.
I would agree with David’s sentiment if it were made clear that he was referring to “high-level components” and not specifically engines. But as I’ve outlined above, an engine is no more accurately generalized as a high-level component than a generator is. And generators, my friends, are sanctioned.
Isn’t This Pleasant?
Engines = (plugins + generators) – (some of the hiccups in both). Nothing more, nothing less. Engines are NOT, by their nature, high-level components. They can be whatever plugins or generators in isolation or combination can be. If Engines are an enabler of bad things, so are plugins and generators. If they are the bringer of doom to the purity of Rails, then generators and plugins were the two horsemen of the Rails Apocalypse.
Am I being a bit melodramic? Yes.
Are we nearly done here? Thankfully, yes.
Am I going to stop asking rhetorical questions? I hope so too.
To My Fellow Rails Application Developers
Please, please please please please everyone. Calm down. Don’t look at Engines and think that you’re suddenly going to be forced to use some monolithic subsystem that requires you to learn a new language just to configure it. If someone tries to force you work with a system like that, I suggest you simply ignore them.
To People Who Think They Might Want To Write An Engine
- Keep things simple. Keep your code focused on doing one thing. Don’t try and be the One True.
- If you are finding that you are hitting namespace problems, your engine probably does too much.
- Avoid using concrete classes whenever possible. Move your logic into modules.
- Keep things REALLY simple.
- Make sure that your views are clean; don’t display global application information in them (the flash, for instance)
- Existing applications are unlikely to be suitable for transformation into engines that everyone can use. The world is your playground though. Open source is neat.
Postscript: Why All This, Now?
Smart guys were working on comprehensive solutions for login/authorisation/security systems for rails long before any of this furore. Did anyone bat an eyelid? Nope. So why are some people reacting strongly when the development community casts an eye at what these stalwart developers are doing? This is my guess.
With the coming of plugins, we’ve seen an explosion in the availability of bolt-ons for your Rails application. It’s tempting to think of these new additions as being a part of what makes us proud to be Rails developers, and that finally we aren’t going to need to think about how to store files in our database because we’ve got a great file_column plugin to do it just nicely. But that’s an illusion, and one that we ALL need to be careful about: it cannot be anything but hypocritical to let ourselves think that we now have an excellent set of semi-official plugins, whilst simultaneously evangelizing against the development of authentication systems, despite the fact that they might just possibly be applicable to a certain, common class of web application.
The beauty of plugins is NOT that they will individually become recommended or ‘sanctioned’ as the way to add specific functions to your Rails application. It’s the fact that they make it easy for us to share our ideas, to cross-polinate our ActiveRecord enhancements and bounce ideas off each other in a semi-organised manner.
So Why All The Commotion About Login Systems, Anyway? I’m Bored!
My guess is this: there’s such a huge influx right now of people coming to Rails that I’m sure many of them are thinking “Well, I see there are a number of login thingies available here, how do I know which one to chose?”. Perhaps the present drive for standardisation is just a vocalisation of this confusion. Take a look at the SHLG wiki page and you’ll get an idea of the confusion I’m talking about.
Rather than telling them “write your own, it’s easy”, why not give them a variety of different systems that they can play with, and encourage them to understand how they work. Then if they feel they need more, they’re in a far better position to start extending/contributing to existing systems, or writing their own.