I would like to add an array field to my table. Normally, I should have done this the first time I created the table:
t.string :names, array: true, default: []
Now that I have already run the migration, could you please provide me the migration command to add this field to my Recipe table?
Thanks.
Because you've already run the migration, it's a better technique to create a new migration to append the new column on to the table, instead of re-running the existing migration to avoid problems with other developers (even though this may not be a concern of yours right now):
rails g migration add_names_to_recipes names:string
Find the newly-created migration and append the following to the relevant column:
class AddNamesToRecipes < ActiveRecord::Migration
def change
add_column :recipes, :names, :string, array: true
end
end
Finally, run rake db:migrate
add_column :names, array: true, default: []
Related
I've already created a model in Rails to collect some user information
I created the columns as :string initially but I've since changed the way this data is looked up and entered by using separate populated models.
Now instead of entering into these fields as string - i want these columns to be "references" instead.
Is there an easy way to change from the string to reference without having to create a new model entirely?
*do not need to save the existing data
Is there any data in the strings you would like to save?
Or is it just because it has the same name?
You don't have to create a new model.
You could create a simple migration
remove_column :table, :your_column_name, :string
add_column :table, :your_column_name, :integer, references: :your_parent_model
You can add a temporary string column to save the string column first:
rails g migration add_temporary_string_column_to_model temporary_string_column:string
And run rails console:
SomeModel.all.each do |some_model|
some_mode.temporary_string_column = some_mode.string_column
some_mode.save
end
And now you can change your original string column's type to references which is an int(4) column in MySQL, migration like this:
class ChangeFormatInSomeTable < ActiveRecord::Migration
def change
change_column :some_table, :string_column, :references
end
end
Finally, you can run rails console again to convert the string data to integer like this:
SomeModel.all.each do |some_model|
some_mode.string_column = some_mode.temporary_string_column.to_i
some_mode.save
end
And at last, remove the temporary string column:
rails g migration remove_temporary_string_column_from_model temporary_string_column
Here is another solution, without dropping the column itself (not exactly in my case). I'm not sure though if this is the best solution.
In my case, I have a tickets table that holds purchase_uid in itself. I decided to keep purchases in another table after making the necessary improvements in our backend. Purchases table has uuid as the primary key. Given this background, here is my migration to change my column into a reference.
class AddPurchaseRelationToTickets < ActiveRecord::Migration[5.2]
def up
change_column :tickets, :purchase_uid, :uuid, references: :purchase, foreign_key: true, using: 'purchase_uid::uuid'
end
def down
change_column :tickets, :purchase_uid, :string
end
end
In my case, since string doesn't automatically cast into uuid, purchase_uid were dropped and recreated as well. However, if you decide to keep the column type same, I don't think it will be a problem.
You can create migrations to serve the exact purpose.
rails generate migration AddAddressToUsers address:references
This will create a migration file in db/migrate directory.
Then run: rails db:migrate to run migration and make changes in your database.
Don't forget to create associations in your models (belongs_to, has_many, etc.) depending on your system structure.
Wanted to add a simpler alternative to the accepted answer that preserves data:
class ChangeStringToInt < ActiveRecord::Migration[5.1]
def up
change_column :table_name, :field_name, :integer, null: false, references: :table_referenced, using: 'field_name::integer'
add_index :chapter_actions, :field_name
end
def down
change_column :table_name, :field_name, :string, null: false, using: 'field_name::character varying'
remove_index :table_name, :field_name
end
end
I'm trying to add indexing to my users table for the email column. Typing rails g migration add_index_to_users_email generates the migration but the function is empty. The snake casing should be correct, so I'm at a loss as to why the migration is being created but the change function inside is empty.
I've also tried AddIndexToUsersName and the same issue arises.
Any direction on what the issue could be would be greatly appreciated. Only thing I can think of is that I'm using Postgres and not MySQL or SQLite, but that wouldn't matter would it?
As far as I know, migration generators only support addition and removal of columns, with a specified modifier. For example, if you wished to add a new string column phone to the users table, you could use the command
rails generate migration AddPhoneToUsers phone:string
Check the Rails Guides for column modifiers. You can try
rails generate migration AddIndexToUsers email:index
to add an index to the existing column. However, I am not sure if generators support column modification. You can write the migration yourself, assuming the email column already exists on the users table:
class AddIndexToUsers < ActiveRecord::Migration
def change
add_index :users, :email
end
end
Have a look at:
http://guides.rubyonrails.org/active_record_migrations.html
The correct command is
rails g migration AddIndexToUsers email:string:index
This will generate:
class AddIndexToUsers < ActiveRecord::Migration
def change
add_column :users, :email, :string
add_index :users, :email
end
end
Edit the migration file and delete the add_column line, then run the migration.
I tried to create a new Link table and specified the necessary columns under migration.
under db/migrate
class CreateLinks < ActiveRecord::Migration
def change
create_table :links do |t|
t.integer :user_id
t.string :url
t.timestamps
end
end
end
class AddTitleToLink < ActiveRecord::Migration
def change
# add_column :links, :user_id, :integer
add_column :links, :title, :string
end
end
When I ran rails console, Link returned
Link(id: integer, created_at: datetime, updated_at: datetime, title: string)
It seems like user_id (the foreign key) and url are missing. Title, which was added later, is in the table.
Did I do anything wrong?
Did you perhaps run the CreateLinks migration before editing it to add the two fields? If so, you can change that file all day long and rake db:migrate will never re-run it. That would explain there being an empty table links, and the field you then added to it in the next migration.
You can step the database back by running rake db:rollback. Try doing that twice, then migrate again.
Can't see any reason for this not to work. Is it possible that you first ran:
rails g model Link
(which generated a migration AND RAN it)
and then you manually added the :url and :user_id?
Try running twice:
rake db:rollback
Then run again
rake db:migrate
which will catch up your manual modifications
Hi guys I would like to know if there's a way not to lose the data if you're trying to rollback your migration just to update the schema ? For example after running rake db:migrate, and after few rounds of data inserted, you want to add in a new attribute to the schema.
So my question is how can i add the new attribute without losing my previous record ? is it possible to do so ? Because all this while i just did by running rake db:rollback STEP= ... and lost all the data i've generated. Just wondering.
Thanks for helping
From:
BC2
if you have an existing table and want to add new attribute in existing table then simple write stand alone migration.
for ex: you have a students table with attribute name, roll_no ... and now u want to add 'address' attribute in students table
$ rails generate migration AddAddressToStudents address:string
will generate
class AddAddressToStudents < ActiveRecord::Migration
def change
add_column :students, :address, :string
end
end
then simply run "rake db:migrate"
You don't need to rollback to update the schema. Just write a new migration to update the existing table.
For example, to add a field to your user table without destroying anything, write a migration like:
class AddFieldsToUser < ActiveRecord::Migration
def change
change_table :users do |t|
t.date :birthday # add new field
t.remove :first # remove a field
t.rename :gender, :sex # rename a field
end
end
end
See here for more info: http://guides.rubyonrails.org/migrations.html#changing-tables
I created a model with an attribute "name" but I want to change it to "username". Everything I've read about database migrations involves creating a class or some complicated stuff. All I want to do is the equivalent of "UPDATE TABLE" in SQL. How do you run a one-time database migration to change this? I'm guessing it'd involve rails console and then some command?
First:
rails g migration rename_name_column_to_username
Then in the generated rename_name_column_to_username.rb migration file:
class RenameNameColumnToUsername < ActiveRecord::Migration
def self.up
rename_column :users, :name, :username
end
def self.down
rename_column :users, :username, :name
end
end
And then rake db:migrate
If you haven't committed the code that originally created the "name" column, you can just go in to the old migration file that created that column and change name to username and then regenerate the schema.
But if you have committed the code, you should create a separate migration file that renames name to username.
This is important to keep track of the versioning of your database. So you should never really use manual SQL (ALTER TABLE ...) to change the schema.
Run rails g migration RenameNameToUsername, which will create a new file in db/migrate.
Open that file, and add this into the self.up section:
rename_column :tablename, :name, :username
Then run rake db:migrate