How to Manually Create a Migration File Rails 4 - ruby-on-rails

As you will see, I'm pretty new to Rails.
I am trying to follow section 3.3.2 in the RailsGuides on Active Record Associations and it says there that when defining a many to many relationship, besides adding the has_and_belongs_to_many directive to the model, you "need to explicitly create the joining table".
It then gives an example of the content of the migration file:
class CreateAssembliesPartsJoinTable < ActiveRecord::Migration
def change
create_table :assemblies_parts, id: false do |t|
t.integer :assembly_id
t.integer :part_id
end
end
end
My question is: what name should I give to that file? I see that the files generated by the rails g ... command are all in the ..db\migrate folder and have a kind of timestamp at the beginning of the file. Can I use any name? I'm afraid to test and mess up the whole thing. I'm used to MS-SQL and being able to see the tables, add/modify columns, etc.
Side question: there are a few files already there, from previous migrations. How does rails know which ones were already run? And what about running them afterwards when deploying to, say, Heroku?

You can give any name to your migrations. Preferably something self explanatory like create_table_something. You can generate a migration by doing
rails generate migration create_assemblies_parts_joins_table
This will generate a file like below in db/migrate folder
<timestamp>_create_assemblies_parts_joins_table
Rails keeps track of already run migrations in scheme_migrations table. It stores the timestamp of all the migrations that are already run
UPDATE:
You can change the table name to whatever you want in the migration file. Table will be created with the name you give in the following line
create_table :assemblies_parts, id: false do |t|
assemblies_parts will be the table name.

You should not build the file from scratch yourself. As #Vimsha has already said - you can run a rails migration to create a join table migration for you.
The rails standard naming for a join table is to take the two names of the models you are joining, and write them in alphabetical order and pluralised.
eg if your models are "user" and "post", it would be "posts_users", but if it were "post" and "comment" it would be "comments_posts"

Related

Database changes not reflecting after Rake and Migrate commands

I am working very first time on Rails Application. I am using Rails 4. As per tutorials and books I used Rails migrate command to generate initial schema. After that I called rake db:migrate. The message says table created but when I go to db/development.sqlite3 I find no table at all.
Following is the code of Migration File
class CreateEvents < ActiveRecord::Migration
def change
create_table :events do |t|
t.string :title
t.text :summary
t.integer :total_impacts #added later but does not reflect in db
t.integer :current_status #added later but does not reflect in db
t.timestamps
end
end
end
What steps am I missing?
Since I am on early stages of Database I rather called db:schema:load after making changes in schema.rb file.
I guess add_column should work too but not sure.
After reading the comments, I assume that the table was successfully created but that it's only a problem with the :total_impacts and :current_status columns.
If you run a migration once, the database knows that it's already been through it and won't run it again unless specified explicitly (rake db:migrate VERSION=...).
So if you write a migration, run it, then update it and try to run it again, the stuff you've just added (like a new column) won't appear in your database (because the migration has already been run in the database point of view).
If you realize after running the migration that you forgot some things, you have two options:
You can write another migration for the things you want to add/delete and run it. (Easy stuff).
You can rollback the migration (play the down part), edit it and run it again (play the up part). This one can be a bit more tricky depending on when you realize your mistake (has some data related to that migration already been added? etc).

Rails Migrations Basic Workflow

Let's say I have a migration that creates a table 'pages' , this is my migration:
class CreatePages < ActiveRecord::Migration
def up
create_table :pages do |t|
t.string "name" , :limit => 50
t.integer "permalink"
t.integer "position"
t.timestamps
end
end
def down
drop_table :pages
end
end
and that I've created the appropriate migration file X_create_pages.rb and ran it(the table is created in the database).
Now after a few days I realize the structure isn't complete and I need to add another column to my pages table .
What is the best practice , do I create a new migration file with add_column method or do I just change the current migration file's up method -e.g just add my columns to the up method (and then move down a version and then up again - so to run the up method?)
The practice should be you create a new migration to add the new column. This becomes the simplest and risk free path. Of course, we can talk about unseen circumstances!
Updating original migration files should not be used after application is released to production; at least this is what the practice should be. But, this also depends on applications, if you don't have a table that is referenced elsewhere then backing up the data, adding the column and restoring the data is also a possibility which is enabled by this approach of directly modifying the original migration file and rolling down that version and migrating up that version again.
While you are on development, the choice I guess is yours. You could choose either!
Once a migration has been checked into source control it shouldn't be changed.
Modifying a migration on your development environment providing it hasn't been checked into source control is perfectly fine.
Once a migration has been checked in it may have been run by your team mates on their development environment or even been deployed and run in production.
Changing previously committed migrations is going to make you very unpopular in your team very quickly as team mates struggle to understand why their database schema is different from yours but all the migrations have been run.

automatic t.timestamps after rails generate model, can I manually remove this in the migration file?

I ran rails generate model XXXX user_id:integer stream_url:text etc
I noticed that t.timestamps was part of the migration file. Can I manually remove this line without causing any problems in the future?
I searched and couldn't find an answer. I just wanted to check in advance before it causes issues down the line.
I'm trying to follow the steps in this link http://ckdake.com/content/2010/posting-to-twitter-from-a-ruby-on-rails-app.html to use the twitter gem
Use rails g model MyModel --no-timestamps
More info with rails g model --help
In rails migration logic t.timestamp is just add two colums created_at, updated_at. Exactly this two columns are required when you forming the model query based on the time created, updated.
If you are not going to use this types of query in future, absolutely you can ignore it.

Rails Migration : adding an extra column to the table for which records are already loaded

I am using rails 2.3.8. I had created a migration for a table called user which currently has plenty of records.
Now the requirement is to add a new column to it.
I had to create a new migration file since rollback would delete the other table data. But adding a new migration did not work.
def self.up
add_column "users", "xyz", :string, :default => "0"
end
What might be the reason?
is it because the data is already loaded?
is it something to do with caching?
Thanks in advance.
Following up on #elmt's comment, you should create migrations using the command in your rails root directory:
script/generate migration <your_migration_name>
So in your case that would be something like this:
script/generate migration add_xyz_to_users
This will create a filename of the form db/migrate/20101122183814_add_xyz_to_users.rb. That's where you should add your migration. If the filename is not named correctly, the migration will not run.
Ben pointed out correctly. That might be due to older migration version number. But can you tell which type of error are you facing? And is it during running migration or what?

Updating models in rails / migrations

Let's say I used the following command to create a "User" model:
script/generate model User username:string
This creates the user.rb file along with the migration rb file to create the Users table. Now, I want to add an email column to my User model. What's the best way to do that? Do I do it manually and write the migration file by hand or is there a shortcut for doing it? If I write the migration by hand, do I have to name it the same way as the previous migration script (with a timestamp in front) to guarantee that it runs after the previous migration?
Don't worry about the timestamp. It will be generated automatically.
You can do a
rails generate migration add_email_to_user email:string
This would automatically create a migration file which would look like this:
class AddEmailToUser < ActiveRecord::Migration
def self.up
add_column :email, :string
end
def self.down
remove_column :email
end
end
the file would have the timestamp in the format YYYYMMDDHHMMSS (For Rails 2.1 and above) appended in front of the filename.
The Guide has information about generating migrations. If you use the rails generator, it will create correctly named files:
ruby script/generate migration AddEmailToUser email:string
Well you can do two things:
1) If you haven't deployed this anywhere yet, or you don't mind dumping the db and running your migrations again, then modify the file. Remove the tables from your db, and run db:migrate. Easy to do this in development.
2) If this app is in production, or you don't want to drop all your tables. Then create a new migration file. Then in this new migration add/modify/drop the column. Then run db:migrate and the new changes will take effect in your table. This is the best practice.
As for naming your migration, timestamps are used because rails will create a table that keeps track of the latest migrations ran. For this, it is better to use the timestamps. But if you choose, you can use your own convention instead of timestamps. Maybe name them 001_migration.rb, 002_migration.rb, etc.
Hope that helps.

Resources