I'm using a User Model in which name column is there, but now I want to add a nickname column with default of nickname being the name of the user in downcase. How this can be achieved?
Asked
Active
Viewed 233 times
-1
-
you want to achieve all this in migration file itself? or it can be in Model? – Sravan Nov 04 '16 at 05:42
-
@Sravan I want it to be done in migration itself – s_a Nov 04 '16 at 05:43
-
you want to add a new column and update the values of all users name to nickname in downcase right? – Sravan Nov 04 '16 at 05:45
-
@Sravan yes correct – s_a Nov 04 '16 at 05:46
-
@Sravan, I have a question suppose in name column name entered is full name and I only want the first name like from "John Doe" I only want the name John to be the nickname in lowercase – s_a Nov 04 '16 at 06:17
-
to achieve this, you can use `user.try(:name).split.first.downcase` – Sravan Nov 04 '16 at 06:29
-
@Sravan Thank you – s_a Nov 04 '16 at 06:30
2 Answers
2
Do it like this,
class AddNicknameToUser < ActiveRecord::Migration
def change
add_column :users, :nickname, :string
User.update_all("nickname = lower(name)")
end
end
I am assuming you are using postgres.Update all will work faster than saving each record.
For mysql:
class AddNicknameToUser < ActiveRecord::Migration
def change
add_column :users, :nickname, :string
User.update_all("nickname = LOWER(name)")
end
end
EDIT: Both versions(with lower and LOWER) will work for postgres and mysql.

dnsh
- 3,516
- 2
- 22
- 47
-
-
-
1Or better, don't use the `User` model (or any other models) in your migration at all and go with a simple `execute 'update users set nickname = lower(name)'`. That helps keep your migrations independent of the current state of your Ruby code and that helps avoid unpleasant problems. Also, `LOWER` and `lower` are the same thing in SQL as SQL isn't case sensitive. – mu is too short Nov 04 '16 at 17:39
0
Since migration files are ruby files
, you can use the rails models
inside the migration files also,
class AddNicknameToUser < ActiveRecord::Migration
def up
add_column :users, :nickname, :string
User.find_each do |user|
user.nickname = user.try(:name).downcase
user.save!
end
end
def down
remove_column :users, :nickname
end
end
You can also use,
User.find_each do |user|
user.update_attributes(:nickname => user.try(:name).downcase)
end
Edit:
As you need to split only first word of the name, you can use,
user.try(:name).split.first.downcase

Sravan
- 18,467
- 3
- 30
- 54
-
2I *strongly* recommend to people that database migrations never use model code. It's often the case that models referenced in these migrations get dramatically altered over time, sometimes even removed, which makes this code non-functional unless someone goes out if their way to update it. You can fix this instead with the (much faster!) `execute "UPDATE users SET nickname=LOWER(nickname)` and do it all in SQL. – tadman Nov 04 '16 at 07:38