Monday, May 10, 2010

Rails 3 templates and engines


What I really wanted to do was to setup a rails 3 environment that uses engines to organize modular functionality.

It has ALWAYS been my experience that any project will quickly get out of hand if the organization is not tackled very early. Rails projects get messy fast. If you are disciplined enough to use modules for functionality then you can avoid some of these issues. But I really don't like having module names that I have to use spread out in my code. (Albeit sometimes a module to separate functionality is the best course of action.) I've always wanted to have my own app namespace for my functionality boundaries. Wouldn't this be nice:



With plugins I got closer. With the gemifcation I got a little help packaging my plugins up and defining dependencies.

Then came along the rails engines plugin. I have to admit I liked it, but never felt comfortable diving in. The reason is that engine plugins required a fair amount of twidling bits in rails to get it working right. Whenever that happens I feel a little exposed. (Not that that is always a bad thing!) We'll good news for me...I waited long enough and rails 3 (and rails 2.3 as well) has engines as first class citizens.

I've spend a few days pushing them around and I like it. With a little work I was able to create some rails templates that will generate a new rails engine. I then configure the hosting app Gemfile to include my engine and I'm off and running. Nice!

I thought I'd share the work I've done for those that want to do something similar.

NOTE: All these samples are for postgres and rspec. On testing, there are many options out there. I happen to dig rspec, if you have not tried it you should. If you care about your data you will stop using mysql or sqllite and start using postgres.

You can find the templates @ http://github.com/voomify/voomify/templates.
(Warning they reference each other using a local path, so you will need to change that if you plan on using them for yourself. You can create a directory ~/dev/voomify/templates and put the templates there and they will work for you.)

If you have not checked out templates for rails 2.3 and rails 3 then you should do some reading. This is not a tutorial. Here are some references to get started with:
http://m.onkey.org/2008/12/4/rails-templates
http://asciicasts.com/episodes/148-app-templates-in-rails-2-3
http://benscofield.com/2009/09/application-templates-in-rails-3/

Here are some sample templates that really helped me get started:
http://github.com/jm/rails-templates

So what do these templates do? Well there are three templates:
1) app.rb - this creates a rails application with rspec and sets it up to be compatible with our engines.
2) engine.rb - this creates a rails application that is also an engine.
3) finailize.rb - this finalizes our application or engine. It is always called at the end of the process.


I then created a litle bash script that will make it easy for me to call these.

Normally I have to put together a long command line:


With this bash script (in ~/.bashrc on ubuntu):

Credit for this goes to: Ryan Bates (http://asciicasts.com/episodes/148-app-templates-in-rails-2-3)

My command line is now much simpler (whew!):


OK time to get cooking. First let's create a rails 3 engine. This engine will be embedded in our application container. It will be setup with rspec and all the proper '.gitignore' files. It will prompt you for the engine name and the database username. (It also adds jeweler to the app gems. We need this because our engines use jeweler to gemify themselves. Maybe in a later post I will figure out how to remove this dependency.)

Side Note: With rails 3 you no longer have to do that messy 'script/generate rspec_XXXX' junk anymore. Rspec is now installed as the default generator and you can simply run 'rails g scaffold ...'. I dig it.



Now let's add some job scaffolding:



The way these engines are setup they are also full blown applications that we can test inside. This way we develop the engine functionality just like we are in any other application. We can run generators, write tests the way we are accustom to. From your perspective it is just a rails app. How easy is that?

Now let's see it running like any other rails app:



Let's goto the jobs and see them in action: http://localhost:3000/jobs

Before we embed this we need to create a gem.


Ok let's embed this into our 'host' application.

Generate the host application:



Add the following to your Gemfile:



Ok now for migrations. We don't have any helpers for migrations yet. So for now you need to copy your engine migration into your app. Something like this:



Now startup your 'host' app and you will see your jobs. Nice! Imagine how modular you could be! Like a lego version of your coding self.



Let's goto the jobs and see them embedded inside our application as a rails 3 engine!: http://localhost:3000/jobs


Using the voomify-jobs.gemspec in the jobs engine directory you can specify gem depenencies. So if your engine depends on other gems you just need to add them here. That includes other engines. Now you can explicitly manage your dependencies. I feel so clean ... you?

Happy engines.

Note: I ran into a bundler, rake, gem install issue that I cover in this post:
Rails 3, Gems, Rake and Bundler

No comments:

Post a Comment