Regenerate ERD after rake db:migrate - ruby-on-rails

I am using http://rails-erd.rubyforge.org/ to generate an ERD - the output is a very nice diagram of my project's object model. There is also a rake task to generate the ERD, generate_erd, that I would like to have invoked automatically after I run rake db:migrate. How do I do that?

The given link by #MaxWilliams is a helpful but I don't think any of those answers quite do what you want. I found this article on Rake Task Overwriting. It's from 2008, but I tried this out and it worked.
I created another .rake file (for organization) and just happened to call mine migrate_and_generate_erb.rake but name it whatever you want.
Inside I just had this:
namespace :db do
task :migrate do
Rake::Task["erd"].invoke
end
end
Basically, according to the article, Rake just keeps appending code implementation to the task if it's already defined.
Now running rake db:migrate also generated me my ERD.
Careful: You'll also want to do the same for db:rollback so that rolling back a migration also updates your ERD.
One last note: consider also just aliasing this (shell command), just in case you'd ever want to run the migrate without generate the ERD, or use environment variables along with your new Rake task.

Related

Rake sequential tasks

I have run into a very strange problem. I have a task which resets my database as so:
task :reset => [:drop, :create, :migrate, :seed]
The problem is, I am receiving errors when seeding because of missing columns which are added in late migration files. One example:
undefined method new_attr= for User
Yet this attribute is already added in a migration. The strange part is, I receive no errors if I run the above tasks separately. Can anybody shed some light? Surely these tasks cannot be run asynchronously.
Another way to avoid errors is to amend my earlier migrations create_ with the new attributes. Then running :reset doesn't trigger errors for those attributes.
The migrations are clearly fine as I can run the above tasks separately, just not bundled under a single task.
maybe you want to make your reset task more explicit?
namespace :db_tasks do
desc "Rebuild development db"
task :rebuild_database, [] => :environment do
raise "Only run in development or staging" if Rails.env.production?
Rake::Task['db:drop'].execute
Rake::Task['db:create'].execute
Rake::Task['db:migrate'].execute
Rake::Task['db:seed'].execute
Rake::Task['db:test:prepare'].execute
end
end
Probably your problem is already solved using this:
rake db:reset
The rake db:reset task will drop the database, recreate it and load the current schema into it.
Have you tried with namespace?
task :reset => [db:drop, db:create, db:migrate, db:seed]
If these rake tasks are executed in the production mode,
model attributes are cached. Even though migrations work perfect, it wont apply to the cached.
This will break your succeeding seed as newly added columns will be missing in the cache.
A possible solution is to reload your rails environment before seeding.

Undo previously seeded data in Rails

I have seeded a row of data to my table by editing db/seed.rb file and executing rake db:seed command. Unknowingly, I put some wrong information in to that row. So I want to remove the previously added row of data. Is there any rake command for the same like rake db:rollback for rake db:migrate.
There are a couple of aspects to this:
1: You want to change the seed data when no other data is present in the database:
You should simply redo the rake db:seed after updating the seed.rb file. Make sure you have MyModel.delete_all before you try to add anything to that model.
2: You want to change the seed data, but there are other data added to the database
This is a bit harder. Often the simplest thing to do here is to manually change the data with either raw sql-statements, or with the use of tools like PhpPpAdmin, PhpMyAdmin etc.
Now, there is possiby one way to hack this together, and that would be to do some voodoo in the seed.rb file. So you could run rake db:seed deseed=true, then in your seed.rb:
if ENV['deseed']
#Do your deseeding action here
else
#Do your seeding here.
end
You could even get real crazy and do something like this:
deseed = ENV['desee']
#DANGER: Dirty hacks upcoming:
deseed? myModelCall = MyModel.method(:destroy_all): myModelCall = MyModel.method(:create)
myModelCall.call :user_id_or_whatevs => 23 #this creates or deletes a MyModel entity with the given parameters
#NOTE this might not work in all cases and I would not necessarily recommend doing this.
#<3uby
I had similar issues when I seeded my data. In fact, I ran the seed command twice and I couldn't find a way to revoke the second seed. However, I had to run rails db:reset command and then run the rails db:seed command again and that fixed the problem for me.

rake db:reset does not populated data

My Environment -> Ruby 1.9.2 and Rails v3.0.5
I noted a strange pattern in rake db:reset. According to rails source code, rake db:reset will => db:drop, db:create and db:migrate. https://github.com/rails/rails/blob/v3.0.5/activerecord/lib/active_record/railties/databases.rake#L159
Setup: One of my migration files have Model.create statements to populate some data (Forgive me, I'm not the one who had put data-filling-code in those migrations :) ..)
Case 1: When I do the steps manually, i mean drop, create, and migrate, one by one - those statements fill data in the table.
Case 2: When I do just rake db:reset, schema is set properly. but the data is not entering the db. Does db:reset skip create/update statements.. I have tried this several times to make sure that I have no faults in the steps I do. I still get this behavior.
what is going wrong here... ?
I think you're reading the wrong line in the source. As I read it:
db:migrate:reset # => [:drop, :create, :migrate]
db:reset # => [:drop, :setup]
So db:reset just create the tables and sets the migrations as if they had been run, without actually running them. db:migrate:reset actually runs each migration.
I had the same problem before but I was running 3.0.3, and it turns out, somehow I manage to mess up the migrations by change the migrations files and not running the migrations(forgot about it or something)...I'll start by checking those files

Adding sample data to database using rake for a rails engine

I am trying out Rails engines by creating a classifieds engine where users can view/post/reply to classifieds.
The main application contains code for user authentication and profiles while there is an engine which I have created which will deal with the classifieds functionality.
Now I want to add some sample data to the database for the classifieds engine. So I created a rake file called 'sample_classifieds_data.rake' in 'vendor/plugins/classifieds/lib/tasks' and I added the yml files in 'vendor/plugins/classifieds/lib/tasks/sample_classifieds_data'
The code of the rake file and a sample yml file can be found here: http://gist.github.com/216776
Now the problem is that when I run the rake task, no error is being thrown but the values are not getting populated in the database.
Any ideas? BTW, it is development environment and the database is the development database.
I ran a similar rake task to populate sample users in the database which worked. the location of that rake file 'sample_data.rake' was located in 'lib/tasks'.
In rails edge, you can use the rake db:seed feature to add datas to your base. See the commit.
The use is pretty simple.
Create a db/seeds.rb file.
And put whatever code you want to seed your database in it.
For example :
Category.create!(:name => 'My Category')
Country.create!(:name => 'Cassoulet Land')
And when you want to seed your database, you could do a rake db:seed
If, for any reason, you do not wish to use edge (which would be comprehensible in a production environment), you can use the Seed Fu plugin, which quite does the trick for you.
Your task looks good. About the only thing would cause your task to fail silently is that the file you're passing to Fixture.new does not point to a yml or csv file.
Double check by modifying the put statement to print the full path of the file it imported, and compare what it prints against your directory structure.
For example, things will fail silently if your fixture files start with a capital letter? Categories.yml instead of categories.yml
The db:seed task was added in Rails 2.3.4. So no need to run edge.
http://weblog.rubyonrails.org/2009/9/4/ruby-on-rails-2-3-4

rake db:migrate doesn't detect new migration?

Experienced with Rails / ActiveRecord 2.1.1
You create a first version with (for example) ruby script\generate scaffold product title:string description:text image_url:string
This create (for example) a migration file called 20080910122415_create_products.rb
You apply the migration with rake db:migrate
Now, you add a field to the product table with ruby script\generate migration add_price_to_product price:decimal
This create a migration file called 20080910125745_add_price_to_product.rb
If you try to run rake db:migrate, it will actually revert the first migration, not apply the next one! So your product table will get destroyed!
But if you ran rake alone, it would have told you that one migration was pending
Pls note that applying rake db:migrate (once the table has been destroyed) will apply all migrations in order.
The only workaround I found is to specify the version of the new migration as in:
rake db:migrate version=20080910125745
So I'm wondering: is this an expected new behavior?
You should be able to use
rake db:migrate:up
to force it to go forward, but then you risk missing interleaved migrations from other people on your team
if you run
rake db:migrate
twice, it will reapply all your migrations.
I encounter the same behavior on windows with SQLite, it might be a bug specific to such an environment.
Edit -- I found why. In the railstie database.rake task you have the following code :
desc "Migrate the database through scripts in db/migrate. Target specific version with VERSION=x. Turn off output with VERBOSE=false."
task :migrate => :environment do
ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
end
Then in my environment variables I have
echo %Version% #=> V3.5.0f
in Ruby
ENV["VERSION"] # => V3.5.0f
ENV["VERSION"].to_i #=>0 not nil !
thus the rake task calls
ActiveRecord::Migrator.migrate("db/migrate/", 0)
and in ActiveRecord::Migrator we have :
class Migrator#:nodoc:
class << self
def migrate(migrations_path, target_version = nil)
case
when target_version.nil? then up(migrations_path, target_version)
when current_version > target_version then down(migrations_path, target_version)
else up(migrations_path, target_version)
end
end
Yes, rake db:migrate VERSION=0 is the long version for rake db:migrate:down
Edit - I would go update the lighthouse bug but I the super company proxy forbids that I connect there
In the meantime you may try to unset Version before you call migrate ...
This is not the expected behaviour. I was going to suggest reporting this as a bug on lighthouse, but I see you've already done so! If you provide some more information (including OS/database/ruby version) I will take a look at it.
I respectfully disagree Tom! this is a bug !! V3.5.0f is not a valid version for rake migrations. Rake should not use it to migrate:down just because ruby chose to consider that "V3.5.0f".to_i is 0 ...
Rake should loudly complain that VERSION is not valid so that users know what is up
(between you and me, checking that the version is a YYYYMMDD formated timestamp by converting to integer is a bit light)
[Damn IE6 that won't allow me to comment ! and no I can't change browser thanks corporate]
Jean,
Thanks a lot for your investigation. You're right, and actually I think you've uncovered a more severe bug, of species 'design bug'.
What's happening is that rake will grab whatever value you pass to the command line and store them as environment variables. The rake tasks that will eventually get called will just pull this values from the environment variable.
When db:migrate queries ENV["VERSION"], it actually requests the version parameter which you set calling rake. When you call rake db:migrate, you don't pass any version.
But we do have an environment variable called VERSION that has been set for other purposes by some other program (I don't which one yet). And the guys behind rake (or behind database.rake) haven't figured this would happen. That's a design bug. At least, they could have used more specific variable names like "RAKE_VERSION" or "RAKE_PARAM_VERSION" instead of just "VERSION".
Tom, I will definitely not close but edit my bug report on lighthouse to reflect these new findings.
And thanks again Jean for your help. I've posted this bug on lighthouse like 5 days agao and still got no answer!
Rollo

Resources