I am using ruby 1.8.7 and rails 1.2.6. (Its old I know. But I have to use it.) I need to add column to users table. I cant use rails generate migration with rails 1.2.6. I need to add a versioned db migrate file. How can I do that?
I want to add product column to users table. I created a file in the db/migrate folder with following contents.
class AddProductToUser < ActiveRecord::Migration
def self.up
add_column :users, :product, :string
end
def self.down
remove_column :users, :product
end
end
I used script/generate migration AddProductToUser. It gives an error as
undefined method 'cache' for Gem:Module.
Any pointers on how to run migration in rails 1.2.6(<2.x) will also be useful.
Your migrate file looks (almost) fine, does the filename match the class name, and does it have a sequence number at the beginning that follows on from the previous migrate?
Slight change:
# db/migrate/123_add_product_to_user.rb
class AddProductToUser < ActiveRecord::Migration
def self.up
add_column :users, :product, :string
end
def self.down
remove_column :users, :product # note sure where radius came from?
end
end
Then should just be run with rake migrate
More info at apidock
Related
What is the command for removing an existing column from a table using migration?
The column I want to remove is: country:string
From the table: sample_apps
To remove a column with migration:
rails g migration Remove..From.. col1:type col2:type col3:type
In your case:
rails g migration RemoveCountryFromSampleApps country:string
This will generate the following migration in Rails 5.0:
class RemoveCountryFromSampleApps < ActiveRecord::Migration[5.0]
def change
remove_column :sample_apps, :country, :string
end
end
Create migration file:
$ rails generate migration RemoveCountryFromSampleApps country:string
In generated migration file:
class RemoveCountryFromSampleApps < ActiveRecord::Migration
def change
remove_column :sample_apps, :country, :string
end
end
Then run:
rake db:migrate
To remove a column(country here) from table(sample_case)
rails generate migration RemoveCountryfromSampleCase country:string
Above command should generate a file YYYYMMDDHHMMSS_remove_countryfrom_sample_case.rb. under db/migrate folder
class RemoveCountryFromSampleCase < ActiveRecord::Migration[5.0]
def change
remove_column :sample_case, :country, :string
end
end
In my case (I was doing it for more than two columns) only this appears
class RemoveCountryFromSampleCase < ActiveRecord::Migration[5.0]
def change
end
end
remove_column line was not there so I added it manually and then fired the command
rails db:migrate
and it worked for me.
References https://stackoverflow.com/a/2963582
&
Ruby guide on Active Record migration
https://edgeguides.rubyonrails.org/active_record_migrations.html
If want to remove the index too, you do with migration too:
rails g migration remove_post_id_from_comments post_id:integer:index
migration file:
class RemovePostIdFromComments < ActiveRecord::Migration
def change
remove_index :comments, :post_id
remove_column :comments, :post_id, :integer
end
end
then run: rake db:migrate
Do you need to specify the type?
Why not just remove_column :sample_apps, :country or remove_column :comments, :post_id for the samples here? Seems to work and removes a chance for error (text or string).
As the title suggests, I accidentally add some random attachment columns to my model. Say I did rails generate paperclip portfolio href
How do I remove those columns created? rails destroy paperclip portfolio href doesnt seem to work!
For recent version rails 4++ Just create a migration Example:
rails g migration remove_attachment_photo_to_course
Then open the migration file
class RemoveAttachmentPhotoToCourse < ActiveRecord::Migration
def change
remove_attachment :courses, :photo
end
end
Then run, to update the table
rake db:migrate
Where:
photo is the name of paperclip attachment you want to remove
courses is the name of table name
I have created a migration file and change the content to:
class RemoveAttachmentHrefToPortfolios < ActiveRecord::Migration
def self.up
remove_attachment :portfolios, :href
end
def self.down
remove_attachment :portfolios, :href
end
end
The problem is it is not the elegant and correct way to do it. I hope someone can improve this answer..
Normally for a migration you run rake db:rollback. Since this was a generator, you can just manually edit the table and drop the columns.
alter table portfolio drop column href_content_type;
alter table portfolio drop column href_file_name;
-- ... etc for each of the Paperclip columns.
You could also create a migration to drop the columns, but that would be overkill unless your whole team also ran the generator or you checked in schema.rb and others ran it also.
Here is an example migration for removing columns:
class RemoveMagazineFromBooks < ActiveRecord::Migration
def change
# This is not used ANYWHERE...
if column_exists? :refinery_books, :magazine
remove_column :refinery_books, :magazine
remove_index :refinery_books, :magazine if index_exists? :refinery_books, :magazine
end
end
end
Notice the test to check if the column is there. Some people may not have run the previous migration and will not have the column.
This comes from the Paperclip documentation:
remove_attachment :portfolios, :href
This will rollback the latest changes to the DB schema:
rake db:rollback
After that, simply delete the migration file.
This is presuming that you didn't commit any of the changes/migrations to a shared repository.
$ rails generate migration RemoveColumnsFromModel portfolio href
should make you a migration that will remove two columns "href" and "portfolio" from some model's table. The migration will look something like:
class RemoveColumnsFromUser < ActiveRecord::Migration
def change
remove_column :users, :foo, :string
remove_column :users, :bar, :string
end
end
Suppose I created a table table in a Rails app. Some time later, I add a column running:
rails generate migration AddUser_idColumnToTable user_id:string.
Then I realize I need to add user_id as an index. I know about the add_index method, but where should this method be called? Am I supposed to run a migration (if yes, which one ?), then adding by hand this method?
You can run another migration, just for the index:
class AddIndexToTable < ActiveRecord::Migration
def change
add_index :table, :user_id
end
end
If you need to create a user_id then it would be a reasonable assumption that you are referencing a user table. In which case the migration shall be:
rails generate migration AddUserRefToProducts user:references
This command will generate the following migration:
class AddUserRefToProducts < ActiveRecord::Migration
def change
add_reference :user, :product, index: true
end
end
After running rake db:migrate both a user_id column and an index will be added to the products table.
In case you just need to add an index to an existing column, e.g. name of a user table, the following technique may be helpful:
rails generate migration AddIndexToUsers name:string:index will generate the following migration:
class AddIndexToUsers < ActiveRecord::Migration
def change
add_column :users, :name, :string
add_index :users, :name
end
end
Delete add_column line and run the migration.
In the case described you could have issued rails generate migration AddIndexIdToTable index_id:integer:index command and then delete add_column line from the generated migration. But I'd rather recommended to undo the initial migration and add reference instead:
rails generate migration RemoveUserIdFromProducts user_id:integer
rails generate migration AddUserRefToProducts user:references
Add in the generated migration after creating the column the following (example)
add_index :photographers, :email, :unique => true
For references you can call
rails generate migration AddUserIdColumnToTable user:references
If in the future you need to add a general index you can launch this
rails g migration AddOrdinationNumberToTable ordination_number:integer:index
Generated code:
class AddOrdinationNumberToTable < ActiveRecord::Migration
def change
add_column :tables, :ordination_number, :integer
add_index :tables, :ordination_number, unique: true
end
end
You can use this, just think Job is the name of the model to which you are adding index cader_id:
class AddCaderIdToJob < ActiveRecord::Migration[5.2]
def change
change_table :jobs do |t|
t.integer :cader_id
t.index :cader_id
end
end
end
For those who are using postgresql db and facing error
StandardError: An error has occurred, this and all later migrations canceled:
=== Dangerous operation detected #strong_migrations ===
Adding an index non-concurrently blocks writes
please refer this article
example:
class AddAncestryToWasteCodes < ActiveRecord::Migration[6.0]
disable_ddl_transaction!
def change
add_column :waste_codes, :ancestry, :string
add_index :waste_codes, :ancestry, algorithm: :concurrently
end
end
Is there a way to change the column names that paperclip uses when generating its database migration? For example, currently a paperclip migration looks like this:
class AddAvatarColumnsToUsers < ActiveRecord::Migration
def self.up
add_attachment :users, :avatar
end
def self.down
remove_attachment :users, :avatar
end
end
And it generates the following in the database:
avatar_file_name
avatar_file_size
avatar_content_type
avatar_updated_at
Ideally I'd like to change the avatar_file_name to correspond to a column in the database called "content". Is this possible?
Renaming columns, to something else than <attachment>_<attribute> will not work in Paperclip.
It mandatorily needs the following 4 attributes for each attachment in the model:
<attachment>_file_name
<attachment>_file_size
<attachment>_content_type
<attachment>_updated_at
Check this post out for a debate on why following a <attachment>_url approach might be better than having a separate model for attachment (<attachment>.url): Paperclip and Inheritance (STI)
For users that leverage S3 or Google Cloud Storage, you may need to move your files to a new directory following on paperclip's file naming scheme. Here is a sample migration to point you in the right direction:
class MovePaperclipAssets < ActiveRecord::Migration
def up
storage = Fog::Storage::Google.new google_storage_access_key_id: ENV["GOOGLE_ACCESS_KEY_ID"],
google_storage_secret_access_key: ENV["GOOGLE_SECRET_ACCESS_KEY"]
bucket = storage.directories.get('bucket-name')
bucket.files.each do |file|
if file.key.starts_with?("original/directory")
newfile = file.key.gsub("original/directory","new/directory")
file.copy('bucket-name', newfile)
file.destroy
end
end
end
def down
storage = Fog::Storage::Google.new google_storage_access_key_id: ENV["GOOGLE_ACCESS_KEY_ID"],
google_storage_secret_access_key: ENV["GOOGLE_SECRET_ACCESS_KEY"]
bucket = storage.directories.get('bucket-name')
bucket.files.each do |file|
if file.key.starts_with?("new/directory")
newfile = file.key.gsub("new/directory","original/directory")
file.copy('bucket-name', newfile)
file.destroy
end
end
end
end
ruby script/generate migration RenameDatabaseColumn
class RenameDatabaseColumn < ActiveRecord::Migration
def self.up
rename_column :user, :avatar_file_name, :user_file_name
rename_column :user, :avatar_file_size, :user_file_size
rename_column :user, :avatar_content_type, :user_content_type
rename_column :user, :avatar_updated_at, :user_updated_at
end
def self.down
# rename back if you need or do something else or do nothing
end
end
Just try the migration may be it will work for you. add column name whatever corresponding column name.
When you run the rails g migration add_avatar_columns_to_users, you can write as you wrote. But if you want to change the column names, go to the migration file and change them as you want as following. Please don't migrate it untill and unless you change the columns.
class AddAvatarColumnsToUsers < ActiveRecord::Migration
def self.up
add_column :users, :your_file_name,:string
add_column :users, :your_content_type, :string
add_column :users, :your_file_size,:integer
add_column :users, :yourfile_updated_at,:datetime
end
def self.down
remove_column :users, :your_file_name
remove_column :users, :your_content_type
remove_column :users, :your_file_size
remove_column :users, :yourfile_updated_at
end
end
Now run rake db:migrate
The above will work for sure. And add your attachments accordinbly.
I need to remove a few columns from my rails model which i already created and have some row entries in that model.
How to do it? Any links which has details for modifying the schema in rails ?
I'm using rails version 3.
To remove a database column, you have to generate a migration:
script/rails g migration RemoveColumns
Then in the self.up class method, remove your columns:
def self.up
remove_column :table_name, :column_name
end
You may want to add them back in the self.down class method as well:
def self.down
add_column :table_name, :column_name, :type
end
The Rails Guide for this goes into much more detail.
If you know the columns you want to remove you can use the convention: Remove..From.. when naming your migrations. Additionally you can include the column names when running the migration command.
The form of the command:
rails g migration Remove..From.. col1:type col2:type col3:type
For example:
rails g migration RemoveProjectIDFromProjects project_id:string
generates the following migration file:
class RemoveProjectIdFromProjects < ActiveRecord::Migration
def self.up
remove_column :projects, :project_id
end
def self.down
add_column :projects, :project_id, :string
end
end
Via command alternative as Add, only change Add to Remove:
Single Column:
rails g migration RemoveColumnFromTable column:type
Multiple Columns:
rails g migration RemoveColumn1AndColumn2FromTable column1:type colummn2:type