Renaming model with migration - ruby-on-rails

I have an existing model 'micropost' and I found out that there is better name for the model to suit my application. What would be the better approach to rename 'micropost' model to 'story' model without affecting its indexes? I am working on Rails 5.0.0.rc1. The migration snippet is:
class CreateMicroposts < ActiveRecord::Migration
def change
create_table :microposts do |t|
t.text :content
t.references :user, index: true
t.timestamps null: false
end
add_index :microposts, [:user_id, :created_at]
end
end

1 .Make migration to change the database table name from micropost to story.
class RenameOldTableToNewTable< ActiveRecord::Migration
def change
rename_table :old_table_name, :new_table_name
end
end
2 .Change manually the Active Record model class into Story

Run command on console:
$ rails g migration RenameMicropostToStory
Edit migration file:
class RenameMicropostToStory < ActiveRecord::Migration
def change
rename_table :microposts, :stories
end
end
then,
$ rake db:migrate

Related

Not sure why i am getting uninitialized constant AddTableDefaults::TableDefault

Created migration using
rails generate migration add_table_defaults
class AddTableDefaults < ActiveRecord::Migration
def up
create_table :table_defaults do |t|
t.string :table_name, null: false, uniq: true
t.jsonb :default_values
end
TableDefault.create(
table_name: 'test',
default_values: [{name:test}]
)
end
def down
drop_table :table_defaults
end
end
Getting the error saying uninitialized constant AddTableDefaults::TableDefault while doing
rake db:migrate
This is straight forward not sure where i am doing wrong, any help is appreciated. Thanks
I'm pretty sure #mr_sudaca's solution works - however if it definitely doesn't, just define the class inside the migration:
class AddTableDefaults < ActiveRecord::Migration
class TableDefault < ActiveRecord::Base; end
def up
create_table :table_defaults do |t|
t.string :table_name, null: false, uniq: true
t.jsonb :default_values
end
TableDefault.create(
table_name: 'test',
default_values: [
{name:test}
]
)
end
def down
drop_table :table_defaults
end
end
Don't name a column on your table table_name. self.table_name is the attribute used by ActiveRecord models to keep track of the track of which table the model reads/writes from and is thus a really bad choice.
Problem Here was model was not available and i was trying to feed the data into the table

Is it possible to invoke change_table from command line with ActiveRecord migrations?

It is possible to invoke a create_table syntax in a migration from command line by specifying the keyword 'Create' in the migration name:
rails g migration CreateMyTables name:string
This will create a migration with the following content:
class CreateMyTables < ActiveRecord::Migration
def change
create_table :my_tables do |t|
t.string :name
end
end
end
I would like to accomplish the same but with the 'Change' keyword. So from the command line I would run:
rails g migration ChangeMyTables user:references
This is what I got:
class ChangeMyTables < ActiveRecord::Migration
def change
end
end
This is what I would expect:
class ChangeMyTables < ActiveRecord::Migration
def change
change_table :my_tables do |t|
t.references :user, index: true
end
end
end
There is a way to add the reference column from command line:
rails g migration AddUserToMyTable user:references
Note: to add the column to the table we use the convention Add[column]To[table] for renaming the migration.
The result will be similar to:
class AddUserToMyTable < ActiveRecord::Migration[5.2]
def change
add_reference :my_tables, :user, foreign_key: true
end
end
Note: foreign_key: true will create the index for you.
Learn more about add_reference.

Change the column in table in ruby on rails

I have a migration file called [timestamp]_create_posts.rb.
I found that I made the column with a wrong data type. I need to make t.text :content instead of t.string :content.
I include the code from the above file:
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.string :content
t.timestamps null: false
end
end
end
I kinda know that I should not directly change the file but rollback migration and change the schema and do the migration again. But I wasn't sure whether that's a right way to do it. It would be really nice if someone can guide me through this. I'm not really familiar with Rails.
You should not rollback anything. You should create a new migration, that will change a column with following content:
class UpdatePostsChangeContentColumn < ActiveRecord::Migration
def change
change_column :posts, :content, :text, limit: 60000 # or whatever
end
end
or, even better, to supply the reasonable rollback of this migration:
class UpdatePostsChangeContentColumn < ActiveRecord::Migration
def up
change_column :posts, :content, :text, limit: 60000 # or whatever
end
# back to previous version
def down
change_column :posts, :content, :string
end
end
The other option if you are just in the development is just to Drop you database and recreate it. Then you can modify that file, but THIS IS NOT ADVISED. I have done this again in development where i didn't care about recreating my database
rake db:drop
rake db:create
rake db:migrate
There are two ways to change the column in table:
You can use rake db:rollback VERSION=file_version and then after that you can change datatype manually.
Generate another migration file. e.g rails g migration RemoveColumnToPost and the you can add following codes:
def up
change_column :posts, :content, :text
end
def down
change_column :posts, :content, :string
end
And then use rake db:migrate

Rails: Adding an index after adding column

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

Alter existing model with a Redmine plugin

The Redmine plugin tutorials explain how to wrap core models but what I need is to add another column to the journals table.
I need a boolean field inserted in the journals model. Creating another model with a 'belongs_to :journal' relation seems like an overkill.
Can this be done with a plugin?
I should note that I am a rails newbie.
You just have to create the appropriate migration.
In your plugin's directory, create the file db/migrate/update_journal.rb with the following :
class UpdateJournal < ActiveRecord::Migration
def self.up
change_table :journal do |t|
t.column :my_bool, :boolean
end
end
def self.down
change_table :journal do |t|
t.remove :my_bool
end
end
end
Then you can execute the task rake db:migrate_plugins RAILS_ENV=production to update your database with the new field.
After executing the migration, your journal database will have the my_bool field that you'll be able to call like every other field.
I was able to extend the existing user model using the following code:
class UpdateUsers < ActiveRecord::Migration
def up
add_column :users, :your_new_column, :string, :default => ''
add_column :users, :your_other_new_column, :string, :default => ''
end
def down
remove_column :users, :your_new_column
remove_column :users, :your_other_new_column
end
end
Also I needed to name the migration file in way that it began with a number eg. myplugin/db/migrate/001_update_user.rb

Resources