I am new in learning ruby on rails, I am confused when to use change_column and when to use t.change for migrations?
For example
class CreateProducts < ActiveRecord::Migration[7.0]
def change
create_table :products do |t|
t.string :name
t.text :description
t.timestamps
end
end
end
The def change method is part of all migrations. This method contains the changes that you want to apply during a given migration.
All your migrations will either have change method or an up and down method. If you define a change method like this:
class CreateProducts < ActiveRecord::Migration[7.0]
def change
create_table :products do |t|
t.string :name
t.text :description
t.timestamps
end
end
end
then when you apply this migration, a table will be created, and when you roll back this migration, Rails will try to generate a reverse of the migration. In this case, the reverse of create_table would be to drop the table.
Now suppose you already have this table created, but then you realize that you want to limit the length of the name field, then you can generate a migration to do that. This migration will use change_column method because you are now trying to change the definition of an existing column.
class LimitProductName < ActiveRecord::Migration[7.0]
def change
change_column :products, :name, :string, limit: 100
end
end
Related
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.
I need to change the id of the existing model to uuid. I'm using this guide:
http://rny.io/rails/postgresql/2013/07/27/use-uuids-in-rails-4-with-postgresql.html
But no idea how to adapt the migration below to changing (not creating a new one):
class CreateDocuments < ActiveRecord::Migration
def change
create_table :documents, id: :uuid do |t|
t.string :title
t.string :author
t.timestamps
end
end
end
Try This.
class documents < ActiveRecord::Migration
def change
add_column :documents, :uuid, :uuid, default: "uuid_generate_v4()", null: false
change_table :documents do |t|
t.remove :id
t.rename :uuid, :id
end
execute "ALTER TABLE documents ADD PRIMARY KEY (id);"
end
end
source
Rails automatically handles uuid, so you just need to change id to uuid, set the column type (uuid for PGSQL, string for MYSQL) and repopulate the table with the new uuid.
In doing this myself, I've only ever changed the id column to uuid for Rails to populate it automatically.
$ rails g migration ChangeID
#db/migrate/change_id______.rb
class ChangeId < ActiveRecord::Migration
def change
rename_column :documents, :id, :uuid
change_column :documents, :uuid, :uuid #-> will only work for PGQL, will have to make it string for MYSQL
end
end
$ rake db:migrate
This will rename your :id column to uuid, assigning the respective column type to it.
And, yes, I've used :uuid before...
--
A good ref:
http://labria.github.io/2013/04/28/rails-4-postgres-uuid-pk-guide/
So I am trying to create three models, Project, Entry and User. A Project has many Entries, and a a User has many Entries. I scaffolded the above three models with the following commands:
rails g scaffold Project title:string
rails g scaffold Entry project:project_id entry_for:user_id created_by:userid \
date:string start_time:string end_time:string total:string type_of_work:string \
on_off_site:string phase:string description:text
rails g scaffold User name:string
I realize that I probably totally goofed up the part where I manually put in the foreign keys for the other tables in the Entry model. I don't know how much has_many belongs_to automates the relationship between different models in terms of keys so I tried to add the foreign key fields manually. Is this wrong?
When I try to run db:migrate I get the following error:
undefined method `user_id' for #<ActiveRecord::ConnectionAdapters::TableDefinition:0x007fc1bdf37970>
Here are my migrations, as I tried to remove all of the foreign key fields but got the above error.
class CreateProjects < ActiveRecord::Migration
def change
create_table :projects do |t|
t.string :name
t.timestamps
end
end
end
class CreateEntries < ActiveRecord::Migration
def change
create_table :entries do |t|
t.string :project
t.string :project_id
t.user_id :entry_for
t.user_id :created_by
t.string :date
t.string :start_time
t.string :end_time
t.string :total
t.string :type_of_work
t.string :on_off_site
t.string :phase
t.text :description
t.timestamps
end
end
end
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.timestamps
end
end
end
class RemoveColumns < ActiveRecord::Migration
def self.up
remove_column :entries, :created_by
remove_column :entries, :entry_for
remove_column :entries, :project_id
end
def self.down
add_column :entries, :created_by, :user_id
add_column :entries, :entry_for , :user_id
add_column :entries, :project_id, :string
end
end
Thank you for your help!
In your migrations, instead of t.user_id you can try t.integer or t.index. That should at least get your migrations running.
I am going to use t.references entry_for and then write belongs_to :entry_for, class_name: "User" in the Entry model as a means of writing my own foreign key name. For the project column in entries I realized I can similarly write t.references project.
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.
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.