Best way to add_index to database - ruby-on-rails

I have the following two migrations already in my database:
When I created Prices:
class CreatePrices < ActiveRecord::Migration
def self.up
create_table :prices do |t|
t.string :price_name
t.decimal :price
t.date :date
t.timestamps
end
# add_index :prices (not added)
end
def self.down
drop_table :prices
end
end
and when I added a user_id to Prices:
class AddUserIdToPrices < ActiveRecord::Migration
def self.up
add_column :prices, :user_id, :integer
end
# add_index :user_id (not added)
end
def self.down
remove_column :prices, :user_id
end
end
Is there a way from the command line to add prices and user_id to index? I looked at this question and still was confused on how to go about adding indexes and the parts where I put "not added" seem like they would be error-prone because they were earlier migrations.
My question is, what is the best way for me to add indexing to prices and user_id?
Thank you for the help!

I think one extra migration fits well:
class AddIndexes < ActiveRecord::Migration
def self.up
add_index :prices, :user_id
add_index :prices, :price
end
def self.down
remove_index :prices, :user_id
remove_index :prices, :price
end
end
Or you can use change syntax with newer versions of rails, look at DonamiteIsTnt comment for details:
class AddIndexes < ActiveRecord::Migration
def change
add_index :prices, :user_id
add_index :prices, :price
end
end

Once an app is in production, the intent is that migrations will be applied once.
If you're still developing your app, you can always add them as you've noted followed by a rake db:migrate:reset this will wipe your database and re-create it.
Otherwise, create a new migration rails g migration add_user_id_index.
class AddUserIdIndex < ActiveRecord::Migration
def self.up
add_index :prices, :user_id
end
def self.down
remove_index :prices, :user_id
end
end
FWIW, add_index :prices doesn't make sense. Indexes are per-column, not per-table.
You can always manually create indexes by logging into your database.
CREATE INDEX prices__user_id__idx ON prices (user_id);

Simple solution:
create a new migration
add the indexes there (they don't need to be in the older migrations)
run the migrations

Related

What is the best practice when it comes to deleting a table in the Ruby on Rails migration?

I created a few tables last week and I was told to delete them. The suggested way in which I should do it looks like this:
Sample table:
class CreateMenuTable < ActiveRecord::Migration
def change
create_table :menus do |t|
t.string :name
t.timestamps null: false
end
end
end
class CreateSpreeMenuRole < ActiveRecord::Migration
def change
create_table :menu_roles do |t|
t.belongs_to :role, class_name: 'Role'
t.belongs_to :menu, class_name: 'Menu'
t.timestamps null: false
end
end
end
step 1. bin/rake db:rollback STEP=6
step 2. after rolling back I have to comment out those tables then
step 3. bin/rake db:migrate
Btw we still have multiple tables created after that, that's why we still need to run migrate.
Generate a migration to drop these tables rails g migration DropMenuTable and rails g migration DropMenuRolesTable
Drop the Tablet by either
migration not reversible
class DropMenuTable < ActiveRecord::Migration
def up
drop_table :menus
end
def down
fail ActiveRecord::IrreversibleMigration
end
end
class DropMenuRolesTable < ActiveRecord::Migration
def up
drop_table :menu_roles
end
def down
fail ActiveRecord::IrreversibleMigration
end
end
or
migration is reversible
class DropMenuTable < ActiveRecord::Migration
def change
drop_table :menues do |t|
t.string :name
t.timestamps null: false
end
end
end
class DropMenuRolesTable < ActiveRecord::Migration
def change
drop_table :menu_roles do |t|
t.belongs_to :role, class_name: 'Role'
t.belongs_to :menu, class_name: 'Menu'
t.timestamps null: false
end
end
end
run rake db:migrate
There will be unsuitable commit if you just comment out migration.
Also you will delete all data in other tables.
So the best practice to drop table via migration like this:
class DropMenuTable < ActiveRecord::Migration
def change
drop_table :menus
end
end
class DropMenuRolesTable < ActiveRecord::Migration
def change
drop_table :menu_roles
end
end
Migrations allow you to evolve your database schema overtime.
When your app is in development it may seem easy to just rollback the migration and make changes, or even delete it. But you shouldn't do it when you have code deployed to production or is sharing code with another developer. Your database will likely become corrupted and will produce hard to fix bugs.
The best thing you can do to delete a table is to create a new migration and drop_table as suggested by spickermann.

What's wrong with my database migrations?

I'm trying to create a situation in which I have the ability to create a series of studies. So I have a table called Series. Each Series will have a name. Each Series also has_many :parts. So I have a table called Part and it belongs_to :series. Then each Part has_many :questions and my Question table belongs_to :part. I have to attribute each of these tables to each other so I have the migrations setup like this:
class CreateSeries < ActiveRecord::Migration
def self.up
create_table :series do |t|
t.string :name
t.timestamps
end
end
def self.down
drop_table :series
end
end
class CreateParts < ActiveRecord::Migration
def self.up
create_table :parts do |t|
t.date :date
t.string :book
t.integer :series_id
t.timestamps
end
add_index :parts, [:series_id, :created_at]
end
def self.down
drop_table :parts
end
end
class CreateQuestions < ActiveRecord::Migration
def self.up
create_table :questions do |t|
t.text :body
t.integer :part_id
t.timestamps
end
add_index :questions, [:part_id, :created_at]
end
def self.down
drop_table :questions
end
end
So I migrated the database and using SQLite DB Browser, my Questions table has a parts_id which it should. And my Parts table should have a series_id column, but it does NOT. Could someone please help with this issue? Thanks.
I wonder why the series column is not in your database. ok to perform a safe check if i may call it try running the model generator again. This time run it like this
rails g model part date:date book series:belongs_to and see if you get the same issue. I hope this helps. Or you can also check with your console window try creating a new part with a random series id and check if it has pluralization issues.
Open the application console rails c and type Part.
You should see the attribute series_id.
If you do, the solution is simply restarting the server.

Change a column name in rails database.

I'm having this table
class CreateEvents < ActiveRecord::Migration
def self.up
create_table :events do |t|
t.integer :subcategory
t.string :event_name
t.text :description
t.string :location
t.date :date
t.decimal :price
t.timestamps
end
end
def self.down
drop_table :events
end
end
and i want to change the subcategory to subcategory_id. I tries this one but is not working
ruby script/generate migration RenameDatabaseColumn and then i went to the file which is in db\migrate and edited to look like this
class RenameDatabaseColumn < ActiveRecord::Migration
def self.up
rename_column :events, :subgategory, :subgategory_id
end
def self.down
# rename back if you need or do something else or do nothing
end
end
then i run the command rake db:migrate put the column is still subcategory. Can you help me please? I'm using rails 2.0
Thank you
Did you misspell the column name? isn't it :subcategory? You wrote :subgategory.
class RenameDatabaseColumn < ActiveRecord::Migration
def self.up
rename_column :events, :subcategory, :subcategory_id
end
def self.down
# rename back if you need or do something else or do nothing
end
end

Rails: How to add add_index to existing table

I already migrated a table called units with several columns. I was wondering how to migrate in a stand alone 'add_index' to this table using the cmd. Is this code correct:
class AddIndexToUnits < ActiveRecord::Migration
def self.up
add_index :units, :lesson_id
end
def self.down
remove :units
end
end
I have a feeling the self.down could be wrong, I am unsure.
The self.up method is correct. Use this for your self.down:
remove_index :units, :column => :lesson_id
Almost
class AddIndexToUnits < ActiveRecord::Migration
def self.up
add_index :units, :lesson_id, :name=>'lesson_index'
end
def self.down
remove_index :units, 'lesson_index'
end
end
To remove an index, you must use remove_index with the same table and column specification as the self.up's add_index has. So:
def self.down
remove_index :units, :lesson_id
end
A multi-column index example would be:
def self.down
remove_index :units, [:lesson_id, :user_id]
end

How do I remove a model and its table in Ruby on Rails?

I'm diving into RoR and I need to remove a model and its table, as well as update the other models that reference it. I did a search on google and SO and the best answer I found was this, but the answer is unclear to me. The final consensus was to use the ruby script/destroy model method and then "manually edit any migrations that might contain refs to these deleted models" It's this last part that I'm unclear about. I want to delete the models for my user and profile models and tables...
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.string :email
t.string :password
t.timestamps
end
end
def self.down
drop_table :users
end
end
class CreateProfiles < ActiveRecord::Migration
def self.up
create_table :profiles do |t|
t.string :name
t.integer :user_id
t.timestamps
end
end
def self.down
drop_table :profiles
end
end
and update the article model and table that references them...
class CreateArticles < ActiveRecord::Migration
def self.up
create_table :articles do |t|
t.string :title
t.text :body
t.datetime :published_at
t.string :image
t.timestamps
end
end
def self.down
drop_table :articles
end
end
class AddUserIdToArticles < ActiveRecord::Migration
def self.up
add_column :articles, :user_id, :integer
end
def self.down
remove_column :articles, :user_id
end
end
Can I just do ruby script/destroy user and then call the self.down methods in the article migrations? If so, how do I call the 'self.down` methods and in what order?
Thanks so much in advance for your help!
Yep. Just delete it with
ruby script/destroy model user
ruby script/destroy model profile
And then rollback your database, or self.down with this :
rake db:rollback
Now you can safely delete your migration file.

Resources