How do I rake in a redefined db table?

I've created a database and my tables. Now in one of my tables I need to edit a field to have a default value and also add another field for parent relationships and wondering how to do that with rake, or if I should use rake.

In my db/migrate/001_create_companies.rb file I originally started with:

class CreateCompanies < ActiveRecord::Migration   def self.up     create_table :companies do |t|       t.string :name, :unique => true, limit => 100       t.text :description       t.string :website, limit => 255       t.integer :position       t.boolean :show, :default => true

      t.timestamps     end   end

  def self.down     drop_table :companies   end end

I would like to update two lines so "position" has a default value of "0" and a foreign key is created for "industry". So I've updated the file to read

class CreateCompanies < ActiveRecord::Migration   def self.up     create_table :companies do |t|       t.string :name, :unique => true, limit => 100       t.text :description       t.string :website, limit => 255       t.integer :position, :default => 0       t.boolean :show, :default => true

      t.references :industry       t.timestamps     end   end

  def self.down     drop_table :companies   end end

The current mysql table has a couple rows of data which I'm okay blowing away but maybe I should just delete the whole table and re-run rake db:migrate to create a fresh version?

Any pointers appreciated.

Thanks, DAN

Hi Dan! (from another Dan),

Take a look here: http://dizzy.co.uk/ruby_on_rails/cheatsheets/rails-migrations

It looks like you can create a new migration and do the two things you need to:

script/generate migration AddIndustryToCompanies industry_id:integer

Then, you should have: db/migrate/002_add_industry_to_companies.rb file. Edit it to add in the position modification:

def self.up   add_column :companies, :industry_id, :integer   change_column :table_companies, :position, :integer, :default => 0 end

def self.down   remove_column :companies, :industry_id   change_column :table_companies, :position, :integer end

This is just off the top of my head (and looking at that cheat sheet).

HTH!

-Danimal

Follow Danimal's instruction, or use db:rollback and db:migrate to re- create the table if you don't want to add another migration file.

Danimal has it right, but if you're okay with a "do over", I'd just run a

rake db:migrate VERSION=0

to get back to a clean DB, then edit my 001 migration to be what I need, and run a straight

rake db:migrate

to reconstruct the database.

I spent a portion of last week reworking my database schema, and collapsing various and sundry "add a field" and "create a view" migrations into a new set (went from 28 migrations to 16). You can also reorder your migrations if you want, there's nothing sacred about 001 versus 002 as long as you honor any dependencies (create tables before views, etc).

Good stuff here. Ultimately, you have to decide your philosophy of DB management. For me, if I'm building something by myself, I don't do multiple migrations. Er... that is to say, once I create 'em & run 'em I usually flatten them back into the 001 migration. This is, of course, only pre-release.

I also created a rake task called "db:remigrate" which does a: db:drop, db:create, db:migrate and data:load so I end up with fresh tables, migrated and populated with some data (I opted not to manage the data via fixtures, but that's just me).

Once I've deployed, though, everything changes. From that point on, 001 is immutable and changes are migrations on top of it, although with the same philosophy except the "flattening" is all post-001 changes flattened into a post-001 migration.

For example, if I made 3 different migration changes since the first release of the app, I'd have 001, 002, 003, and 004, but then before i released the changes to the live app, I'd flatten 002 - 004 into a single 002 migration. That one then becomes the next immutable one.

This, of course, is only when I'm building the app myself. When in a team, it's a different process altogether.

-Danimal

Ar Chron wrote:

(create tables before views, etc).

Thanks for the great info and insights.

Should I be able to re-create the views after re-raking?

In 2.02 I think the creation of a controller, model, view, and a db/migrate/file is condensed into one command line such as:

script/generate scaffold store name:string address:string zip:integer state:references position:integer

It's still a little foggy for me though so any clarity appreciated.

Thanks, DAN

Dan Poynor wrote:

Should I be able to re-create the views after re-raking?

Sure. Just make sure your view migrations also drop the view on a "down" invocation, and you can happily rake up or down your versions, and all the pieces and parts will be maintained.

class CreateScenarioviews < ActiveRecord::Migration   def self.up     x_sql = "CREATE OR REPLACE VIEW `scenarioviews` AS SELECT "     x_sql += "`s`.`id` AS `id`,"     x_sql += "`s`.`scen_name` AS `scen_name`,"

    blah blah blah

    x_sql += " FROM (`scenarios` `s`"     x_sql += " JOIN `projects` `p` ON (`s`.`project_id` = `p`.`id`))"     execute x_sql   end

  def self.down     execute "DROP VIEW `scenarioviews`"   end end

Of course, after posting, I realized that you might be thinking about the MVC view, where I was talking about database views..... my bad.

You'll still have to update the generated xxx.html.erb views yourself as you add/remove fields from a model. It's the generator that writes the initial view code from your:

script/generate scaffold store name:string address:string zip:integer state:references position:integer

command. There might be a "de-generate" generator command lurking somewhere where you could rake db:migrate VERSION=0, then degenerate your model, views and controller to begin anew, but I haven't found the need (yet) to see if it really exists.

ruby script/generate scaffold shortlived

... followed by

ruby script/destroy scaffold shortlived

did work.

It seems a bit overzealous to me... I just tried it in a tester application I keep around (just for this kind of stuff), and it wiped the scaffold.css (good reason not to use the default .css), but did clear the test, model, and views for the shortlived model...

As long as you're not working with multiple developers, all on
different database versions, or a production database that has been
migrated and also has in-use data in it!

Julian

Learn Ruby on Rails! CHECK OUT THE FREE VIDS (LIMITED TIME) NEW VIDEO
OUT 3rd APRIL http://sensei.zenunit.com/