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

You can provide them at generation time:

    script/generate scaffold Post title:string body:text category_id:integer

--Jeremy

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

If you find anything, let me know.

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.

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

Hi Roy,

Roy Pardee wrote:

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?

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

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?

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.

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...

Roy Pardee 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].

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

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 <<model name>> 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. # -------------------------------------------------

Roy Pardee 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 <<model name>> 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.

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 Pardee 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

Why, no--I haven't. :wink: That looks perfect--thanks!

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

Tonypm