Reputation: 95
I have the following model :
Class User::Basic
belongs_to: group
Class Group
has_many: users
class_name: "::User::Basic",
foreign_key: "group_id"
I also have a User::Admin
class, which does not belongs to the group class (group_id equals -1)
I have an existing database where groups do not exist. I am trying to edit the group of basic users through the migrations.
In my migrations I have :
add_column :users, :group_id, :integer, :default => -1 #so that when a group_id is not specified, the user is ranked as admin
# I create groups 1,2,3 and 4 and then :
User.find(21, 3, 8, 17, 16, 18, 14, 19, 23, 25, 26).each do |usr|
usr.update_attributes(group_id: 2)
end
User.find(11, 13, 20, 9).each do |usr|
usr.update_attributes(group_id: 1)
end
User.find(15,22).each do |usr|
usr.update_attributes(group_id: 3)
end
User.find(24).update_attributes(group_id: 4)
But all users still have a group_id of -1 after running the migrations. I tried to run the last bit in a console and it worked, so does anybody knows why this is not working in migrations ?
Upvotes: 0
Views: 452
Reputation: 76784
Console
I personally would not include the data-specific calls in a migration, it's simply not what the migrations are for:
Migrations are a convenient way to alter your database schema over time in a consistent and easy way. They use a Ruby DSL so that you don't have to write SQL by hand, allowing your schema and changes to be database independent.
You can think of each migration as being a new 'version' of the database. A schema starts off with nothing in it, and each migration modifies it to add or remove tables, columns, or entries. Active Record knows how to update your schema along this timeline, bringing it from whatever point it is in the history to the latest version. Active Record will also update your db/schema.rb file to match the up-to-date structure of your database.
I wouldn't mention this if you were using a sweeping statement such as User.all
etc, but as you're selecting individual records (with the find
method), you'll make your migrations VERY data-specific, which isn't what they're for
If you push this to production, and have different
ids
, how will it work?
Simply don't perform database requests in your migration
--
I would recommend making your migration specifically for your column:
#db/migrate/your_migration.rb
class YourMigration
def change
add_column :users, :group_id, :integer, :default => -1
end
end
Then once this has run, you'll want to use the rails console to perform the data-specific fixes you want:
rails c
groups = {"1" => [11, 13, 20, 9], "2" => [21, 3, 8, 17, 16, 18, 14, 19, 23, 25, 26], "3" => [15,22], "4" => [24]}
groups.each do |group, users|
usr = User.find(users)
usr.update_attributes(group_id: group)
end
Upvotes: 2
Reputation: 9747
Whenever we run the migrations, rails resets the columns information about the tables, after completion of the execution of migration file.
In your case, you are trying to access the column before the completion of migration file execution. So, you need to call reset_column_information
explicitly before operating on the column you have just added from the same migration file.
Here is an example:
def change
add_column :users, :name, :string
User.reset_column_information
User.all.each do |u|
u.name = 'user name'
u.save!
end
end
Upvotes: 1