Rails 3 Rake Clone Database for Testing Environment - ruby-on-rails

Is there a rake command in Rails 3 to clone my development database data? I noticed rake db:test:prepare and rake db:test:clone are mentioned throughout various blogs, but running them seems to do nothing. Furthermore, rake -T shows no db:test cases. I've resorted to loading a sql dump for now, but it would be great if I could just clone my existing development data for up-to-date testing.
EDIT --
I desire to test on a database since I am dealing with legacy data that I run through model filters when accessed. Factories won't work for me in this context, since data passed through create is defined as a different schema than that of the legacy data.

rake db:test:prepare is still there even though it doesn't show up in rake -Tdb. I guess the Rails team decided to de-clutter the rake -T output?

I would suggest you not clone your development database but rather rely on factories to give you predictable data you can craft for your exact test cases. Sooner or later, relying on having reliable test data in a database you can access will break your tests. It will also break the tests of anyone else who works on the project. And changes/additions to the data will not propagate to other developers as would your carefully constructed factories.
Look over Machinist, FixJour, FactoryGirl and the lot. They really solve the test data problem well and you check them into version control so the rest of your team has access to them.

Related

rake db:migrate doesn't generate table in postgresql

I've been having a problem which doesn't seem uncommon (I've read a lot of stack overflow pages in the last 2 days) but every solution I've read hasn't worked for me.
I've been following this video tutorial
At 6:42 the tutor shows the tables in postgresql and mine don't show up.
When I try rake db:migrate the files migrate no problem. rake doesn't throw up any errors, the relevant .rb files are created in the models folder, my schema.rb looks right. It seems postgresql just isn't reading my schema file.
My problem sounds identical to
rake db:migrate doesn't seem to work in production
However typing rake db:migrate RAILS_ENV=production doesn't work. (I've tried this a few times after other rake commands like rake db:rollback STEP=3 in the past few days because I was paranoid it was the solution, this person on ruby forum, has the same problem and is offered the same answer).
This is my first attempt at programming anything and I'm loving the tutorial (and the learning curve this problem has turned out to be) Asking here is pretty much my last resort because I've tried everything I can understand online as a possible solution so please help me! Thanks a lot in advance
There is quite a bit of confusion going on here:
Migrations
Migrations are a convenient way to alter your database schema over
time in a consistent and easy way. They use a Ruby DSL so that you
don't have to write SQL by hand, allowing your schema and changes to
be database independent.
Postgres does not read your schema file or migrations - rather migrations run SQL queries against your database. In this case a CREATE TABLE ... query will be run when the migration is run.
Migrations are basically a more maintainable and sane way of doing what was classically done by opening a DB console and running SQL queries.
config/schema.rb is not actually used by the database or ActiveRecord - rather its created when you run migrations as a snapshot of what the database schema should look like. Its just a developer convenience. ActiveRecord gets its mappings by querying the database schema.
Migrations and generators
Migrations do not create model files either - those are generators such as:
rails g model Dude abides:boolean
Which creates a CreateDudes migration and a model at app/models/dude.rb.
In fact migrations are just concerned about altering the DB schema and don't care if the model file exists or not - the models is not actually used until you query the database for records.
ENV vars
RAILS_ENV=production sets a environmental variable.
rake db:migrate RAILS_ENV=test
Is the documented way to run a migration in a different environment. Some obscure shells require the ENV var to prefix the command.
However - if you are running a production server you should set the RAILS_ENV env var permanently - not on invocation! This prevents embarrassing misstakes when someone expected you to have configured the server properly and just ran rails s when restarting the server. See the documentation for your server OS on how to set env vars.
If you are still running the migration and do not see the expected results you most likely have not configured config/database.yml properly - the migrations are running. But not against the database you would expect.
http://guides.rubyonrails.org/active_record_migrations.html

How to make db:test:purge only drop a schema on postresql?

I'm using postgresql on a rails 3 app. I've been using sqlite3 for test environment, but decided to finally switch to the same db I use in production for testing purposes. Problem is, I'm only creating one database and diverse schemas for each environment. This is somethiing I can't change, since the environment is enterprise-constrained.
Hence, I have a test schema. I rund db:schema:load on it and it works fine. I run rake spec on it (I'm using rspec) and it breaks, exactly on the 'db:test:purge' task which comes from rails. Now, this task drops the database. Not only is the database owner different from the schema owner in my case, I'd rather have the task recreate the schema instead of recreating the database.
How can I do this?
Actually there is no real solution for this problem, since rails by default erases the database. It expects this database not to be shared with production (and they might have a point). Nevertheless, I found some interesting links and the way is to patch the rake task. Following the patch and links:
namespace :db do
namespace :test do
task :purge do
ActiveRecord::Migration.verbose = false
Rake::Task["db:schema:load"].invoke
end
end
end
https://github.com/rails/rails/issues/12117#issuecomment-25961999
Run Rails Tests without Dropping Test Database
http://www.pervasivecode.com/blog/2007/09/22/making-rails-raketest-not-drop-your-pgsql-database/
This is not a direct answer to your question, but you can use rspec command instead of rake spec. rspec command doesn't purge your database.

Rake in Rails: should I be using db:reset?

I'm a little confused by the intended use of the default Rails Rake tasks, and would like advice on whether I should be using db:reset or writing a custom Rake task. Nothing clever, just daily housekeeping, and I may well be missing an obvious doc as I'm new to Rails.
My problem: I want to throw away my database and run from a completely clean setup, in order that I can be sure the database contains known data only. This is useful for demo prep, for debugging, and for making sure Jenkins is comparing like-with-like in tests.
Currently, I'm writing this:
bin/rake db:drop:all db:create:all db:migrate db:seed db:test:prepare
This is a lot to type, but leaves seed data only in both dev and test databases. I am unsure how this differs from db:reset, which would be more convenient to type.
Should I use db:reset or write a custom db:from_scratch task?
You should be using:
rake db:reset
This will drop the database, recreate it and load the current schema into it.
For a full list of rake db tasks:
rake --describe db
If your requirements change then it would be better to write a custom rake task, where you can apply your own customisation.
If you're not sure what a rake task does, then I would suggest not using it. In this case, you're probably ok, however db:reset is not the equivalent to what you are doing above. db:reset recreates the database from scheme.rb, this may be different as you could have written migrations that have not yet been run.
I would suggest that you use a custom rake task, you can then modify it to fit your exact purposes, especially if you want to perform other tasks as well (for example tagging in git)
What you are trying to achieve in your the tasks you are running through rake is setting both the test and the development databases. rake db:reset will just do it for your current environment db according to the schema.rb and then load the seeds data into the db. The schema.rb in general is never edited, its for a know-only/refer-only purpose, however some people do tend have different schema.rb which might create a problem :(. What sounds better to me is if you need to set both your development and test database, then run your migrations for the dev environment and use the schema.rb to create the test environment db. I would definitely suggest you to get a second opinion from some Rails guru though to find out a real perfect way to achieve what you want.
rake db:reset
This will drop the database, recreate it and load the current schema into it.
rake db:reset will run rake db:seed
Example :
if you have seed file that you wrote after you ran your migration , it will run that too.

Rails 2.3.5 table populated by fixtures at end of test run rather than at start

I start with a test database containing the schema but with no data in the tables. I run a test like so
cd test/
ruby unit/directive_test.rb
I get failures indicating that the code found no data in the data tables. However, I look at the tables after running that test and the data is now in the the table. In fact, if I immediately run the test again I get no failures.
So it appears that the fixture is being loaded into the table too late for one of my modules to find it.
When are the fixtures loaded? After or before the app/model/*.rb files are executed?
If it is after the models are executed is there a way to delay the loading?
This issue is also relevant when running rake test:units since that task clears the test data after it finished.
first of all see this thread and see if it can help you.
if you run the rail task rake test:units it will for sure load all fixtures before you run your code. if you are running just the test, and your unit test has no reference to the test_help.rb probably it is not loading the fixtures. You should try to run it through the rake tasks.
Another tip that i give you is that you forget the fixtures and use factories (here i recommend factory_girl). It takes sometime to get used, but it worth. Fixtures are too hard to manage, update and etc.
there is another post explaing little about the concept behind factories.

How to handle one-off deployment tasks with capistrano?

I am currently trying to automate the deployment process of our rails app as much as possible, so that a clean build on the CI server can trigger an automated deployment on a test server.
But I have run into a bit of a snag with the following scenario:
I have added the friendly_id gem to the application. There's a migration that creates all the necessary tables. But to fill these tables, I need to call a rake task.
Now, this rake tasks only has to be called once, so adding it to the deployment script would be overkill.
Ideally, I am looking for something like migrations, but instead of the database, it should keep track of scripts that need to be called during a deployment. Does such a beast already exist?
Looks like after_party gem does exactly what you want.
I can't think of anything that does exactly what you want, but if you just need to be able to run tasks on remote servers in a one off fashion you could always use rake through capistrano.
There's an SO question for that here: How do I run a rake task from Capistrano?, which also links to this article http://ananelson.com/said/on/2007/12/30/remote-rake-tasks-with-capistrano/.
Edit: I wonder if it's possible to create a migration which doesn't do any database changes, but just invokes a rake task? Rake::Task["task:name"].invoke. Worth a try?
I would consider that running that rake task is part of the migration to using friendly_id. Sure, you've created the tables, but you're not done yet! You still have to do some data updates before you've truly migrated.
Call the rake task from your migration. It'll update the existing data and new records will be handled by your app logic in the future.

Resources