-1

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?

dnsh
  • 3,516
  • 2
  • 22
  • 47
s_a
  • 65
  • 9

2 Answers2

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
  • Actually, I'm using MySQL – s_a Nov 04 '16 at 06:02
  • The second version should work in both MySQL and Postgres. – tadman Nov 04 '16 at 07:38
  • 1
    Or 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
  • 2
    I *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