Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you create a "temporary" model in Rails migration?

I have a Rails 2 project that has a many-many relationship through a join table. Let's call the tables A, B, and ABJ, where ABJ has properties a_id and b_id (along with irrelevant-to-this-question id and {created,updated}_at).

What I want to do

This relationship was unfortunately created incorrectly from the beginning, and should have been simply one-many (A has_many B's, B belongs_to A). So I created an up migration that reassociates the B's directly to the A's. Basically goes, 1) add_column a_id to B, 2) for every ABJ, put abj.a.id into abj.b.a_id, 3) drop_table :abj. This works fine.

I also created the "inverse" operation in the down migration to go back if I need to (1) create_table abj, 2) for every B, make a new abj such that abj.a_id = b.a_id and abj.b_id = b.id, 3) remove_column a_id from B). This works fine too.

Problem

Along with "re-associating" this relationship to a one-many is the expectation that the no-longer-used join resource ABJ will go away, i.e., deleting the model, controller, tests, etc. The problem is that if I do need to go back, running the down migration won't work because at step 2 (for every B, make a new abj) there is no longer any class ABJ < ActiveRecord::Base since I deleted the model.

So is there any way to make a "temporary" model within a migration just for the sake of manipulating data in the DB? Or do you simply require that the person running the migration needs to be certain that this model exists before running it? Because if the down migration fails at step 2, then step 1 would have already created the abj table, and then you'd have to go manually remove it or comment out the step 1 code in the migration before running it again (then uncomment it afterward).

Wondering if there is any nice solution to this.

like image 550
istrasci Avatar asked Feb 08 '12 18:02

istrasci


People also ask

What can Rails migration do?

A Rails migration is a tool for changing an application's database schema. Instead of managing SQL scripts, you define database changes in a domain-specific language (DSL). The code is database-independent, so you can easily move your app to a new platform.

Where are Rails migrations stored?

Every Rails app has a special directory— db/migrate —where all migrations are stored. Let's start with a migration that creates the table events into our database. This command generates a timestamped file 20200405103635_create_events. rb in the db/migrate directory.

How do you run down migration in Rails?

To run a specific migration up or down, use db:migrate:up or db:migrate:down . The version number in the above commands is the numeric prefix in the migration's filename. For example, to migrate to the migration 20160515085959_add_name_to_users. rb , you would use 20160515085959 as the version number.


2 Answers

You can define a model in a migration. Simply put a barebones definition at the top of your migration:

class Pancake < ActiveRecord::Base; end

In a case where you're dropping a table you need to be careful that you're not calling methods on Pancake when the pancakes table doesn't exist.

like image 65
Tom L Avatar answered Sep 20 '22 00:09

Tom L


Either go with TomL's advice or go with manual SQL (assuming you use MySQL):

UPDATE
  B, ABJ
SET
  B.a_id = ABJ.a_id
WHERE
  B.id = ABJ.b_id;

Other RDBMSes allow similiar, more natural syntax using JOINs.

like image 36
Marcel Jackwerth Avatar answered Sep 22 '22 00:09

Marcel Jackwerth