Reputation: 77
I'm adding a new column to the table in Rails app and not sure how to set a default value through constant
I defined constant in User.rb model:
USER_TYPE = [
{ id: 1, name: "User" },
{ id: 2, name: "Admin" },
{ id: 3, name: "Super Admin" }
].freeze
and generated new migration
class AddAccountTypeIdInAccounts < ActiveRecord::Migration[5.2]
def change
add_column :users, :user_type_id, :integer, :default => ?
end
end
What should be instead of '?' to save USER_TYPE with id 1 and name "User" from constant as the default value of new User?
Upvotes: 0
Views: 200
Reputation: 117
As your specific question was answered in the last comment I'll let some points just to drive your imagination to better options you have for this problem.
Let's imagine if tomorrow you need to change the default value of this specific column, you will need to create a new migration, and if you need to change this 20 times you'll need to create 20 new migrations.
The option above is not scalable.
You should probably let the default nil
in migration and use ActiveRecord
callbacks or even better another module (service or action) that will take care of the create action to you and set the default value.
# models/user
# option 1
class User < ApplicationRecord
USER_TYPE = [
{ id: 1, name: "User" },
{ id: 2, name: "Admin" },
{ id: 3, name: "Super Admin" }
].freeze
before_create do
self.user_type_id = USER_TYPE.first[:id]
end
end
# services/user_creator_service
# option 2
class UserCreatorService
def self.call(user)
user.user_type_id = User::USER_TYPE.first[:id]
user.save
end
end
Upvotes: 0
Reputation: 10054
add_column :users, :user_type_id, :integer, :default => 1
Seriously, why do you want to define the default based off of a constant that lives in the app code? The migration is something that you will run at a certain point in time, it's not code that you'll maintain down the line. There's little point in referencing app code in migrations because the app will evolve and references will change. You don't want to maintain migrations.
Of course you could also reference the value stored in that constant, maybe it serves as documentation for you. In that case:
add_column :users, :user_type_id, :integer, :default => User::USER_TYPE.first[:id]
(Not sure if USER_TYPE
is defined inside class User
; if not, omit User::
above.)
Upvotes: 3