Rails 2 scaffolding: establishing the field list

Hey All,

Is there a way to get the scaffold generator in rails v2.0.2 to read
field names out of an existing table? I get that you can list them
off on the command line when you generate the scaffold, and get the
whole kit & caboodle.

But I’d really like to:

  • generate the migration
  • edit the migration (specifing field lengths, nullability, etc.)
  • run the migration
  • generate the scaffold.

Is that doable w/the new rails out of the box, or is there a plugin
that does it, or am I just out of luck?

Thanks!

-Roy

Hmm–just read the big foofaraw on the philosophy of rails 2
scaffolding, and looked at http://activescaffold.com. What I’m
looking for is static scaffolding that will ‘introspect’ an existing
table (I think that’s the right terminology…). It looks to me like
activescaffold is dynamic.

I just want some training wheels to lean on until I can get the bike
going fast enough not to need them. :wink: (In my case I’m (re)learning
html/css, etc. and those scaffold-generated files are very very
helpful…)

Thanks!

-Roy

activescaffold rocks, but it is only so customisable (very
customisable, but if you’re just learning css/html again, well, might
be tough). And it is dynamic, which is cool.

Building your own scaffold is in the end more fulfilling and useful
when you’re asked to do something specific. I usually start with
Rails’ scaffold from the generator so i get my controller logic, then
build up the views as I need. I don’t think there’s a replacement in
Rails 2x for the old style auto-scaffold, but at the end of the day it
was kinda all for show :wink:

You might also like the make_resourceful plugin, which takes a lot of
the repetition out of making restful controllers. It also means you
can customise your default views easily, so you do less mucking about
tweaking layouts of admin pages and more building the fun stuff.

You can provide them at generation time:

script/generate scaffold Post title:string body:text 

category_id:integer

–Jeremy

On Tue, Mar 4, 2008 at 3:57 PM, Roy P. [email protected] wrote:

  • edit the migration (specifing field lengths, nullability, etc.)


http://jeremymcanally.com/
http://entp.com

Read my books:
Ruby in Practice (Ruby in Practice)
My free Ruby e-book (http://humblelittlerubybook.com/)

Or, my blogs:

http://rubyinpractice.com

Thanks for the response! I can definitely appreciate that writing
your own views/controllers/etc. is the way to go long term, I’m just
trying to get my sea legs here.

I’ll have a look at make_resourceful–thanks. I have only a dim idea
of what REST is (address bar = command line?) so being RESTful is not
a conscious goal of mine right now, but I’m not against it or
anything… :wink:

I would definitely still like to know tho if there’s an introspecting
static scaffold generator out there somewhere…

Thanks!

-Roy

If you find anything, let me know.

Heh–perhaps one day when I’m an Nth-level Rails Mage I shall write
one. :wink:

On Mar 5, 11:26 am, Roy P. [email protected] wrote:

Heh–perhaps one day when I’m an Nth-level Rails Mage I shall write
one. :wink:

Perhaps the hardest nut to crack here is what the expected behavior of
such a static scaffold tool is. What you describe is a generator, but
generators can be destructive. Say you did something like:

script/generate keen_scaffold post

And presto! It examines an existing database table called posts,
creates model, views and controllers. Ok, time goes on and you’ve
fleshed this out with a bit of your own code. and then:

script/generate keen_scaffold post

What is the generator supposed to do? Volunteer to overwrite your code
if you like?

I’m not sure what value this would offer over the current script/
scaffold beyond having some views hooked up.

How did you envision this working?

Hi Roy,

Roy P. wrote:

  • run the migration
  • generate the scaffold.

Is that doable w/the new rails out of the box,
or is there a plugin that does it, or am I just
out of luck?

AFAIK, the short answer to your first question is no. You’ll need to
specify the fields on the command line when you generate the scaffold.
The
answer to your second question, I think, is no. You’re not out of luck.
You can specify some of the fields on the command line when you generate
the
scaffold, edit the migration to add the remainder of the fields, and
then
run the migration. You’ll have to edit the new/edit/show views to add
the
new fields, but if you choose the ones you specify on the command line
so
that you’ve got one of each type that exists in the table you’re
modeling,
then it’s pretty much a cut-n-paste. So if you’d be happy with…

  • generate the scaffold
  • edit the migration (specifing the additional fields, field lengths,
    nullability, etc.)
  • run the migration
  • edit the new/edit/show views (adding the fields you decided not to
    initially specify)

then you’re in luck.

HTH,
Bill

Re: what should a good static introspective scaffold generator do when
invoked > once: Yep–I would expect it to offer to overwrite any
files that already exist. (I think that’s what the existing scaffold
does.)

I’m really envisioning this as a kick-start for trivial apps–a use-
once crutch for newbies that want to play with something, but want to
generate an app w/models that have more than 3 or 4 attributes (after
which point it becomes awkward IMHO to list everything out on the
command line). The only time you’d re-generate the same scaffold is
when your subsequent edits really horked something, and you’re
desperate enough to want to trash it all & start again.

Thanks!

-Roy

That sounds intriguing. Where would I find rails’ scaffold
generator? I wonder if I could just get in there & monkey w/the
arguments that are passed…

On Mar 5, 12:07 pm, Mark B. [email protected]

Wildtangent wrote:

Building your own scaffold is in the end more fulfilling and useful
when you’re asked to do something specific. I usually start with
Rails’ scaffold from the generator so i get my controller logic, then
build up the views as I need.

I’ll second that. I’m putting together a little Rails presentation with
demo for work. To help things along I decided to do a little work up
front on my own scaffold generator. Based on the existing one I created
my own which creates layouts and styles with the same look & feel as our
existing web apps. Five commands in the shell, switch to the browser
and there’s something familiar to look at already.

Roy P. wrote:

That sounds intriguing. Where would I find rails’ scaffold
generator? I wonder if I could just get in there & monkey w/the
arguments that are passed…

The existing generator is in:

[GEM_HOME]/gems/rails-2.0.2/lib/rails_generator/generators/components/scaffold

(depending on your version of Rails - run “gem environment” to see where
your gems are).

Rails will look for generators in ~/.rails (on UNIX/MacOS - don’t know
about Windows) so if you wanted your generator to be called “funky”:

mkdir -p ~/.rails/generators/funky
cp -r
[GEM_HOME]/gems/rails-2.0.2/lib/rails_generator/generators/components/scaffold/*
~/.rails/generators/funky
cd ~/.rails/generators/funky
mv scaffold_generator.rb funky_generator.rb

Then edit funky_generator.rb and replace the class name
ScaffoldGenerator with FunkyGenerator and also update the “banner”
method.

Now, in any Rails application you can use:

script/generate funky MyModel field1:type1 field2:type2 …

and get the same results as the standard scaffold.

Now, update the USAGE file to be more relevant to your scaffolding and
update the contents of the template directory accordingly.

Note that the template files are run through ERb when scaffolding
happens, so ERb commands that need to remain will start with “<%%”.
That is, where you see “<%%”, this will get passed through as “<%” and
where you see “<%”, this will get evaluated and the result passed
through.

Any processing you want to do for creating the scaffold and any files
you want/don’t want to create are specified in funky_generator.rb.

To make the generator available to all users, turn it into a gem and
install it in [GEM_HOME].

Ah–looks like I don’t have to care about inheritance hierarchy–I can
just munge runtime_args (proof of concept below).

Now all I need is to figure out how to get the field names/types out
of the db. I wonder if I can just try to create an instance of
<> and reflect on it… Suggestions welcome!

Thanks all!

-Roy

-------------------------------------------------

def initialize(runtime_args, runtime_options = {})

# This is hokey, but it's within my powers.
# TODO: check for --skip-timestamps and --skip-migration and

handle those gracefully.
if runtime_args.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 with just a single argument–looking for table
called "’ + si_table_name + ‘"’ )
# Proof of concept…
si_field_names = %w(yabba:string dabba:text doo:date)

  # TODO: use whatever ActiveRecord goo is responsible for the

dynamic models to pull
# name/type pairs out of table(si_table_name) in the current
environment.

  runtime_args += si_field_names

  # no need for a migration in this case...
  runtime_args += %w(--skip-migration)
else
  puts(runtime_args.inspect)
end

super

# etc.

-------------------------------------------------

Thanks!

It’s probably insane of me, but scaffold_generator.rb doesn’t actually
look that that daunting (I’m more of a ruby & database guy than a web
guy). I guess I’ll have to spelunk through the inheritance hierarchy
a bit to figure out how runtime_args gets parsed… But I’ll have a
look & see what I can see.

Thanks!

-Roy

I actually had a hard time trying to create a new AR class to do the
reflection. You can’t just put a “class Foo ; end” in the middle of a
method. You also apparently can’t just create a phony class deriving
from AR:Base–when I tried to instantiate that I got an AR exception
complaining that there was no table on the db called
my_phoney_class_names. :stuck_out_tongue:

But–this does seem to work to pull column objects out of the db for
a given name:

si_cols = ActiveRecord::Base.connection.columns(si_table_name,
“#{name} Columns”)

I can loop through the collection I get there, like so:

si_cols.each do |c|
si_field_names << “#{c.name}:#{c.type}”
end

And a spot-test seems to indicate that my scaffold can work & allows
me to work according to my desired sequence.

So–here’s my next question–are their tests for the basic scaffold
generator that I can clone to test my generator? Sniffing the folders
around the scaffold generator file has revealed only templates for
generating tests.

Thanks all!

-Roy

Roy P. wrote:

Now all I need is to figure out how to get the field names/types out
of the db. I wonder if I can just try to create an instance of
<> and reflect on it… Suggestions welcome!

The model might not already exist, but you could create one locally on
the fly in the scaffolder and reflect on that. The class method
#column_names provides you with a list of column names.

It’s probably insane of me, but scaffold_generator.rb doesn’t actually
look that that daunting

No, it’s fairly straightforward. Look at:

[GEM_HOME]/gems/rails-2.0.2/lib/rails_generator/base.rb

for the parent class of the scaffolder to see more of what’s going on.

It’s easier than it sounds. And if anyone intends creating a number of
applications with the same look and feel then it’s definitely worthwhile
creating your own scaffolder, or at least your own generator which can
create the structure, stylesheets and layouts you want.

Roy P. wrote:

So–here’s my next question–are their tests for the basic scaffold
generator that I can clone to test my generator? Sniffing the folders
around the scaffold generator file has revealed only templates for
generating tests.

Thanks all!

-Roy

Have you checked the svn repository for the Rails trunk?

http://svn.rubyonrails.org/rails/trunk/railties/test/generators/rails_scaffold_generator_test.rb

anyone know if there is a scaffold generator (option) that creates
views in haml?

Tonypm

Why, no–I haven’t. :wink: That looks perfect–thanks!

On Mar 8, 8:51 pm, James B. [email protected]