Dr Nic

[BTS] Magic Models – Class creation

[BTS] = Behind the Scenes; also a news-like TV show we used to watch as school kids (in Australia) that explored world news events and then our teachers would make us write reports about it. (UPDATE: this is a lie; it was BTN – Behind the News) Anyway….

Class creation – the magical way

As an educational exercise, it is definitely interesting to look at how the Magic Model’s Invisible Classes [1] are generated. Inside the gem [2], please turn to the file /lib/module.rb I’ve broken it up below too.

class Module
  alias :normal_const_missing :const_missing

  def const_missing(class_id)
    begin; return normal_const_missing(class_id); rescue; end

If you open the Irb/Console and type Foo, you’ll get an “unitialized constant Foo” error. This is raised by the const_missing method in the Module class. Yes, there’s a core class called Module. Type Module.methods.sort to see all the fun things it can do, or look up the API.

Like so many things in Ruby you can override this method, just like you might override the method_missing on a class (Rails does this on its ActiveRecord to support the find_by_... magical methods.)

When you load Magic Models (via the require 'dr_nic_magic_models' statement) it renames/aliases the current const_missing method and then overrides it.

The first thing it does it call the original const_missing to see if it returns anything useful. Why? Rails also overrides this method. Rails doesn’t preload all your model classes at start up. Instead when you first ask for a model class, it loads it via the const_missing method call. So Magic Models won’t do anything until Rails has had a chance to try an load the class from a app/models/foo.rb file, for example.

    unless table_name = DrNicMagicModels::Schema.models[class_id]
      raise NameError.new("uninitialized constant #{class_id}") if
                    DrNicMagicModels::Schema.models.enquired? class_id
    end

The DNMM::Schema class is in charge of mapping an unknown class name (class_id) to one of your database’s tables. To prevent nasty infinite recursion, we raise the “uninitialized constant” error if another const_missing request comes in for the same class_id.

    klass = Class.new ActiveRecord::Base
    const_set class_id, klass

The Class API takes a superclass as a parameter. Here, we want our Invisible Model to be an ActiveRecord.

By setting the anonymous class object to a constant value, e.g. Foo, it automatically names the class. E.g. klass.name == 'Foo'

    klass.set_table_name table_name

Finally, we force the new ActiveRecord class to use the table name that DNMM::Scheme found. You just can’t trust that the class will know what its table name is.

If you find yourself using this sort of code, then here’s some bonus code. When you create your class, you can install some code at the same time.

    klass_code = %q{def to_s; 'I''m magically generated'; end }
    klass_code = lambda {klass_code}
    klass = Class.new ActiveRecord::Base, &klass_code

Feedback

Was this easy to read? Too compact/too long? Let me know below.

If you go on and build something magically cool after reading this, definitely let me know.

Moral of the Story

You can live as a programmer without ever knowing any meta-programming features of Ruby. Heck, we all did it in Java/C++/C# and never knew we needed them. A lot of powerful API features exist in Rails that you’d never be able to build in many other languages; the ActiveRecord library is a tribute to meta-programming magic.

UPDATE: I had previously called Module a module, when its a class. Fixed.

[1] I just like calling them Invisible Models.

[2] Gems are installed inside your Ruby installation folder. Try something like ....\lib\ruby\gems\1.8\gems\ and you'll see all your favourite gems, like rails-1.1.5, active-record-1.14.4, etc.

Hosted Gmail

First there was email. Time passed. Then there was Gmail.

Hosted Gmail in Action I’m not writing to convince non-Gmail users to use Gmail. I’m writing show this screen shot of Hosted Gmail in action. It’s a beta mail hosting service on top of the beta gmail service, so assuming beta < 1, therefore beta*beta < beta; ergo, it may be worse than gmail alone. But I'm prepared for any possible punishment. Gmail is just that wonderful.

The hosting solution may seem redundant for people who've setup email forwarding from their non-gmail accounts to gmail, but Hosted Gmail would seem a cleaner solution, with unlimited potential. Currently that potential begins with allowing the management of additional users. Its a start.

Dr Nic's Wish: Hosted Gmail to provide "public" access to each others' emails within your domain (or subgroups) so that knowledge that accumulates within email boxes can be shared more easily.

Dr Nic's History: when I first learnt Ruby on Rails, the first thing I did was build a Gmail clone. This was pre-RJS days and before I discovered TrimPath, so the Javascript usage was clunky, and it sent a lot of HTML back to the browser instead of JSON data. But it was lovely.

Gmail Hosted: https://www.google.com/hosted

TextMate theme for RadRails

Radrails with Textmate themeUPDATE: Screen shot of Textmate theme for Radrails now available.

UPDATE: Vista ClearType fonts available now. I’ve also added instructions for changing fonts in RadRails if you cannot install Consolas, below.

RadRails comes with one theme: white background, black foreground. A few nice shades of markup. Lovely.

Want a little more excitement? Perhaps you want to feel like your using TextMate, even though it costs 30€ and won’t run on your machine anyway?

What you need is the TextMate-theme for RadRails. My friend Brett devised this and gave it to me during Railsconf. Understand this with me – he drove 15 hours from southern USA to Chicago. I flew 20 hours from Amsterdam. Just so I could get this theme and now share it with you.

That’s one prized theme right there, all y’alls. (A Texan taught me that once).

Download it, unzip it, and store it anywhere you like. Don’t like free choice? Then save it in the RadRails/Themes.

If my memory serves me well:

  1. Go to File > Import…
  2. Under General, select Preferences, and click Next.
  3. Browse to the epf file.
  4. Select the Import All checkbox and press Finish.

You are now one sexy Ruby/Rails developer. Yes, you.

UPDATE: The theme will look for the Consolas font – one of the new Windows Vista fonts that you can download after a bit of Googling – its the replacement for Courier New.

UPDATE: If you cannot install Consolas on your system, you will need to select an alternate fixed width font, such as Courier. To do this:

  1. Go to Window >> Preferences…
  2. Go to General >> Appearance >> Colors and Fonts
  3. Select Basic >> Text Font
  4. Click Change…
  5. Select your replacement fixed width font, and press Ok.

[ANN] Dr Nic’s Magic Models

Magic hatWelcome! Welcome! Welcome! Ladies and Gentlemen, today you shall be thrilled and dazzled by wonders of magical mystery. Dr Nic’s Magic Models will now be unveiled to all. Mystery and magic that you will be able to perform at home.
Within your ActiveRecord models, never again will you need to write:

  • validates_presence_of validations
  • has_many and belongs_to statements
  • has_many :through statements!!

And for the finale, you will be amazed and astounded as you watch ActiveRecord models appear from nowhere. No class definition, just any old database tables you have lying around the home is all you’ll need to perform this trick!

No cover charge. No free steak knives. No heavy lifting involved.

Installation, DIY magical instructions, and a world of mystery awaits you at:
http://magicmodels.rubyforge.org

Original forum notification: http://www.ruby-forum.com/topic/74957

UPDATE: Digg this!

UPDATE 2: Conversations about the Magic Models have been conducted on Ruby/Rails forums too:

Rails docco drive

Twently minutes after you finished all the free Rails tutorials you could find you started reading the Rails API documentation. Twenty-one minutes after the tutorials you start reading the raw Rails code because the documentation didn’t help. To be fair – that was my experience a year ago (mid 2005) – and the documentation is 100s% better now.

But how good could it be? Chip in and find out. Time will prove that you were a Rails pioneer. Make the path easier for those who follow us. Spot some cash to make better Rails documentation.