Where art thou generator?

Posted by Dr Nic on June 25, 2007

Summary: click to select

UPDATE: Rails Generators within RubyGems support is now in Rails Edge

Generators in Rails are awesome. No? So you don’t use the rails command to create a new rails app? Nor the model, migration, or plugin generators? Yeah, they are awesome. Hug the next one you meet.

On my part-time quest to replace the use of Plugins with RubyGems within Rails, it occurred to Geoffrey Grosenbach [1] and myself that there is no easy way to bundle rails generators within RubyGems. Patooey, we say!

Currently, there are several places you can store Rails generators:

  • Builtin ones – like model, scaffold etc – are stored in the rails gem.
  • ~/.rails/generators/ for your own personal generators.
  • Rubygems whose name ends with _generator, such as ajax_scaffold_generator
  • vendor/generators/
  • vendor/plugins/_some_plugin_/generators/ – the most common mechanism for deploying generators

But no way to bundle multiple generators in a RubyGem or have a gem without _generator in its name. And Rails has laid claim to the _generator namespace, which is a bit greedy.

This is outrageous!

Damn it, you’re right! Its now in Rails Edge!

rails newapp
cd newapp
rake rails:freeze:edge

So try out this new Rails Core patch. Never touched a raw patch before? Nevermind. To play with it, let’s create a new rails app:

cd vendor/rails/railties
wget http://dev.rubyonrails.org/attachment/ticket/8730/gem_generators.patch?format=txt -O gem_generators.patch
patch -p0 < gem_generators.patch
cd ../../..

The world’s first Generator-Enabled RubyGem is…

So you can play with this fabbo new feature and explore how to add generators to your RubyGems, Rick Olson’s restful_authentication plugin has been ported into a RubyGem. It is currently available for manual download and will soon be live on RubyForge.

wget http://drnicwilliams.com/wp-content/ruby/gems/restful_authentication-1.0.0.gem
gem install restful_authentication
ruby script/generate

And you’ll see the authenticated generator is discovered from the RubyGem. Neat. Note, we didn’t install the old plugin within the rails app.

So, now let’s play with it…

ruby script/generate authenticated user

It works exactly like it did from the original plugin. But now its a RubyGem, and you never ever need to reinstall this plugin for each new app, ever again. Ever.

Merge plugin generators into RubyGems

There exists a RubyGem daemons, and there exists a separate plugin, that makes it easy to use daemons via your rails app.

This separation will be no longer necessary!

Now the generator code can be moved into the daemons gem itself.

Have a look at the plugin, and note the generators folder. Simply copy this folder into the daemons gem. Then rename this folder to rails_generators. Repackage and release.

Shaazam!

PS. To the owner of daemons repository, come on dude! Upgrade from CVS to SVN:)

Want to write your own generators?

There is some useful info on writing generators on the tubes. Start there.

In all cases, (for an example “foo” generator) the generator file must be called foo_generator.rb, and it must contain a class called FooGenerator.

Does it work with “vendor everything?”

Normal people living normal lives won’t know there exists a Rails Core ticket to support “vendor everything”, created by Marcel Molina Jr [2] (and his backing singer Dave Thomas).

This allows you to store gem files in a /vendor/gems folder, and it will be super magically exploded into the /vendor/gems/home folder. That is, you can freeze raw gems into your rails source structure.

To test this, first uninstall the restful_authentication gem and then reload it into the /vendor/gems folder:

gem uninstall restful_authentication
cd vendor/rails/railties
wget http://dev.rubyonrails.org/attachment/ticket/8511/gems_loaded_from_vendor_like_plugins.diff?format=txt -O gems_loaded.patch
patch -p0 < gems_loaded.patch
cd ../../..
ruby script/generate

Do this just to confirm that the authenticated generate is no longer available.

cd vendor
ls .

Note that you now have a gems folder, and within it you have a home folder, which itself stores lots more new folders. This is Marcel’s patch in action!

cd gems
wget http://drnicwilliams.com/wp-content/ruby/gems/restful_authentication-1.0.0.gem
cd ../..
ruby script/generate

And the authenticated generator is back! Discovered auto-magically from within your own rails source! Investigate the vendor/gems/home folders at your leisure.

So this article is about two things…

Herein layeth a tale of two tickets (first one is now in Rails Edge). Sneaky, nay?

Please try them out and comment within each ticket about any praise/thoughts/fixes/outright-damnations so the nice Rails Core team (esp. to DHH who is not sure if “vendor everything” is something that should be in Rails Core [3]) know this is an important direction for Rails to go.


[1] Normally I’d reference/link
Nuby On Rails or Peepcode, but I just love the “half a head” self-photo on his home page.


[2] More info about Marcel on
Rails Core page.


[3] Based on a chat in irc #rails-contrib the other day, when that ticket was first created.

Trackbacks

Use this link to trackback from your own site.

Comments

Leave a response

  1. Mislav Mon, 25 Jun 2007 17:31:26 UTC

    This is totally awesome! I’ve been using restful_authentication for quite a long time and *hated* that I have to install the generator in every single project. I kept thinking one should come up with a better way, a gem-powered way … and here you are to respond to my pleas :) Thank you!

  2. Chris Mon, 25 Jun 2007 20:14:55 UTC

    This is absolutely delicious.

  3. topfunky Tue, 26 Jun 2007 06:25:01 UTC

    I tried to hack Hoe to accomodate this, but patching Rails will make things much easier.

  4. Robert Tue, 26 Jun 2007 16:51:21 UTC

    This is something that has been bothering me lately and I personally think this is a good way to go. As far as I see it, plugins are to extend Rails Core, not provide an application module like authentication - where the plugin then becomes useless because it has created a file in your lib/ folder.

    I’m also not sure if the solution is putting the GEM inside the Rails application either, when we are talking about running a generator that writes code to our lib/ file and is never used again. It wouldn’t make sense to me to keep that GEM, that is never used again, in our application/vendor/gem.

    However, I believe all generators ought to move to the way of GEMS instead of plugins. Plugins should be for extending Rails and anything that will generate code for your application and not for Rails, should be a GEM.

  5. Dr Nic Tue, 26 Jun 2007 17:02:52 UTC

    @Robert - I’m sorry for the confusion on gems in rails - I wasn’t inferring that gems should be put in the /vendor/gems folder at all. I was actually trying to publicize the concept and show that the two patches work together. I probably shouldn’t have blurred the original purpose of the article.

  6. Robert Tue, 26 Jun 2007 17:15:00 UTC

    @Nic: Ah ok, my bad. I should have read your article *after* I had my caffiene. :) Then I completely agree with you!

  7. Mislav Tue, 26 Jun 2007 17:56:39 UTC

    In your code there is mention of “script/generator” - it should be “script/generate”.

  8. Dr Nic Tue, 26 Jun 2007 19:26:08 UTC

    @mislav - thx, fixed

  9. Matt Aimonetti Thu, 28 Jun 2007 03:40:44 UTC

    Congrats, your patch made it to Edge :) http://dev.rubyonrails.org/changeset/7139

    Thanks for a great new feature and you just need to check out Edge to give it a try. (no monkey patching needed) :)

  10. Dr Nic Thu, 28 Jun 2007 09:41:56 UTC

    @matt - sweet; my first core contribution :D

    I’ll update the description from “patch this” to “go get yourself some sweet edge sexiness” soon.

  11. Luke Melia Fri, 29 Jun 2007 18:12:01 UTC

    Great stuff! All aboard the gem train.

  12. Wellbutrin xl. Thu, 06 Sep 2007 05:49:02 UTC

    Wellbutrin….

    Where can i purchase wellbutrin. Wellbutrin….

  13. [...] found so far is Akita’s tutorial. So far I have restful_authentication working (from the restful_authentication gem), a “welcome” controller and two domain-specific models. I’m working on two [...]

Comments