Monday, March 10, 2008

I am a leet rails haxor...

Been playing with Rails a bit, to see how easy it is for me to learn (since I have some nodding familiarity with Ruby). It's generally fun, but I really disliked the new (in v2) style scaffolding. Apparently, the scaffold generator no longer inspects any existing tables in generating the views. You've got to list everything out on the command line. Very disappointing. I whined about it here.

Encouraged by the kind folks on the Rails Talk group, I tried writing my own scaffold generator--generally a complete ripoff of the original, except that if you don't specify any attributes on the command line, it sniffs the db for a table w/the proper name & then packs the arguments with whatever it finds. It's not fully tested, but seems to work for me. Here is the relevant code:


def initialize(runtime_args, runtime_options = {})

# TODO: test this proper (adapt rails' scaffold_test.rb)
# This is hokey, but it's within my powers.
# Rescue the noob who generates scaffold
# on an existing table w/out specifying attributes
# on the command line.
si_uncounted_arguments = %w(--skip-timestamps --skip-migration)
if (runtime_args - si_uncounted_arguments).length == 1 then
# Called in "static introspective" mode--pack
# runtime_args with name:type pairs if we find
# an existing table.
si_table_name = runtime_args[0].pluralize.underscore
puts("Called without any attribute specs on the command
line--looking for a table called '#{si_table_name}'
from which to infer attributes...")
begin
si_cols = ActiveRecord::Base.connection.columns(si_table_name, "#{name} Columns")
rescue ActiveRecord::StatementInvalid => err
# Table not found.
puts("Sorry--table '#{si_table_name}' not found--you're
going to have a lame-ass scaffold. Did you forget
to run 'rake db:migrate' maybe?")
else
si_attributes = []
si_ignorable_fields = %w(id:integer created_at:datetime updated_at:datetime)
si_cols.each do |c|
si_attributes << "#{c.name}:#{c.type}"
end
si_attributes -= si_ignorable_fields
runtime_args += si_attributes
# No need for a migration in this case--we're using the existing table.
runtime_args += %w(--skip-migration) unless
runtime_args.include?('--skip-migration')
end
else
puts("User specified attributes on the command
line--no introspection done.")
end

super

#etc.

end



I think this will work well enough for my purposes. I'll be using it (gotta get back to trying to learn Rails) for my toy app & will see if it serves me. If it does, maybe I'll try to gem it up (or package it up however such things get packaged up) and put it someplace accessible. In the meantime feel free to steal it, suggest improvements, make fun of it, etc.