Developing an engine: What should I keep in mind?


#1

Hi all

I’d like to begin with clean development of engines that I will be able
to re-use and give to the Rails community.
Now my question: what should I always keep in mind when writing code for
an engine? I’m thinking here about stuff like that I shouldn’t hard-code
table names etc.

And by the way: Isn’t it quite dangerous to hard-code model names, too?
We’re nearly forced to do this, I know, but it could be quite often the
case that the name of an engine’s model is the same like the name of
another model, right? That’s quite dangerous… :-/

Thanks for infos! :slight_smile:
Joshua


#2

What you should keep in mind when developing an Engine:

Keep it focused

Don’t try and solve 1000, 100, or even 10 problems. Do one thing, pick
one strategy, and do it cleanly and clearly.

Convention over configuration

Don’t add configuration until YOU need it, and even then think hard
about whether or not it’s the right thing to do. Engines aren’t
all-terrain vehicles - they should expect to be allowed to do their
own thing to the greater extent, and your application, being more
flexible, should cope with how the engine works [1].

Make it modular

Try and put code into modules wherever you can - it helps with
namespacing, and makes it simpler to override code in the case of
models.

Document like your life depends on it

If you are anticipating that ANYONE else might be wanting to use this
code, make sure that you’ve got a great set of documentation (READMEs,
RDoc, the works) to support it. You’ll save yourself a lot of time in
front of an email client if you do.

… those are a few things to bear in mind, I guess. But here’s the
doozy:

Screw the community - write it for yourself.

It’s only through need that you discover what features are really
important, and only through the need for reuse that you get a deeper
understanding of which aspects of your code can afford to be a bit
more flexible. Write your engine with YOUR needs in mind, and don’t
try and anticipate problems until you hit them yourself.

Once you have a solid understanding of what you’re trying to do, then
by all means let other people in on the project. But always bear in
mind that code is only really useful when it has a purpose, and if
you’re not using it yourself then how can you really understand what
it should do?

… OK, here’s some more practical advice:

  • Put your controllers into modules.
  • Provide a sensible set of routes for the user to use, and use them
    religiously for redirects and link_to calls in your own views [2]
  • Document! (Yeah, I already said that, but it’s crucial)
  • Put model code in modules
  • Try and provide a set of useful partials, rather than a smaller set
    of views, as these are easier to reuse.

Good luck!

  • james

[1] People email me asking how to get the login engine to work with
their application, which has been designed to use Account models
rather than Users. The short answer is… you can’t. Sure, there are
hacks and ways around this, but your life is a lot simpler if your
application has been designed in harmony with the external code it’s
going to interact with, rather than trying to shoehorn everything
together after the fact. Don’t try and please everyone, because design
by committee produces camels, not racehorses
(http://www.pfc.org.uk/medical/mmacvw.htm).

[2] There’s no automatic mechanism for including routes with an
engine, but simply provide some that can by copy-pasted into the
application’s routes.rb file. That’s fine and possibly even
preferable.


#3

#if forum /* May 14, 07:05 */

Hi all

I’d like to begin with clean development of engines that I will be able
to re-use and give to the Rails community.
Now my question: what should I always keep in mind when writing code for
an engine? I’m thinking here about stuff like that I shouldn’t hard-code
table names etc.

I’ll dive in on this last question:
There’s no need to hard-code table names, have a look at:
user_engine/lib/user_engine.rb, notably this part:

The names of the new Role and Permission tables

if ActiveRecord::Base.pluralize_table_names
config :role_table, “roles”
config :permission_table, “permissions”
else
config :role_table, “role”
config :permission_table, “permission”
end

IIUC you could override the actual table names by placing directives
into $RAILS_ROOT/config/environment.rb, like this:

module UserEngine
config :role_table, “my_roles”
config :permission_table, “my_perms”
end

Then, when you actually come to use the table names, say for example in
a JOIN thats tucked away in your code, you can pick out the table name:

UserEngine.config(:role_table)

and use it like:
:joins => "INNER JOIN #{UserEngine.config(:role_table)} ON " +
“#{UserEngine.config(:role_table)}.somefield = " +
" some_table.some_column”

And if you want the the class name, you could do:

UserEngine.config(:role_table).classify

which would pick out “Role”

using these techniques, i believe you can decouple the table names and
classes from your code.

Although, the class names may still conflict with other ones, if you
choose generic names.

HTH at least a little.


keys: http://codex.net/gpg.asc

[a] The Japanese eat very little fat and suffer fewer heart attacks
than
the British or Americans.

[b] On the other hand, the French eat a lot of fat and also suffer
fewer
heart attacks than the British or Americans.

[c] Conclusion: Eat what you like. It’s speaking English that kills
you.


#4

Thanks a lot for your input, Vincent. What you describe is a very
fundamental part of developing an engine, I think. :slight_smile:


#5

Hey thanks a lot for this great points. :slight_smile: As a newbie I still got some
questions though…

Make it modular

How exactly would you do that? If you have a model models/my_model.rb,
where would you put the module’s code? Maybe under
models/my_model_module.rb or so? And then just use include
‘my_model_module.rb’ within my_model.rb? Can you please give me an
example for this?

Document like your life depends on it

That’s a very good point. Is there further documentation how to document
a Rails project/engine?

  • Put your controllers into modules.
    Can you please give me an example for this, too?
  • Provide a sensible set of routes for the user to use, and use them
    religiously for redirects and link_to calls in your own views [2]
    Why no simply use the standard route? If I write other routes - won’t
    this mean more configuration than convention?
  • Try and provide a set of useful partials, rather than a smaller set
    of views, as these are easier to reuse.
    You mean that someone who wants to alter the design maybe just can
    include some partials he likes and rewrites some he needs else?

Thanks a lot for your great answer. :slight_smile:


#6

Please do be careful before you make things too generic, though.
Develop only what you need, and then abstract afterwards.

  • James