When registering as a user using Devise in Rails, I think that there are times when I want to divide the attributes by parameters while using the same model, but surprisingly there is no article that says this, so I will write it as an article. It is assumed that there is a registration link for other attributes in addition to the new registration and login links (see here for premium membership registration). We want to divide this into attributes by giving parameters such as Boolean while reusing the view and controller with one User model. I would be grateful if you could point out any mistakes.
console
Windows10
ruby 2.6.6
Rails 6.0.3.1
psql (PostgreSQL) 12.3
First, add a column to attribute the existing User model (this time isPremium: boolean). The addition of this column is also quite mysterious for beginners, and at first I was not sure and tried to add it to the existing migraition file, but apparently the migration file used when first rails db: migrate was read. Absent? It seems. So create another migration file and write a method to add columns to it.
console
rails g migration AddCulumnToTable
The part of AddCulmnToTable is an arbitrary class name, but usually it seems that something that is easy to understand later, such as Add + column name To table name to be added, is good.
Add the following to the migration file you created earlier.
2020~~_add_column_to_table.rb
def change
add_column :users, :isPremium, :boolean #add to
change_column_null :users, :isPremium, false, false #add to
change_column_default :users, :isPremium, from: nil, to: false #add to
end
In the part of "add_column: users,: isPremium,: boolean", a column called isPremium of boolean type is added to the users table. Null is prohibited by "change_column_null: users,: isPremium, false, false". But the existing user doesn't have an isPremium column (null), so set it to false as well. "Change_column_default: users,: isPremium, from: nil, to: false" sets the default value. When add_column is done, the default value is "Null", so it is changed to false.
console
rails db:migrate
The database should be updated based on the migration file you just created.
In Devise, you can set email and password by default, but when you add other columns, set something called Strong Parameters (username, isPremium this time, etc.).
application_controller.rb
before_action :configure_permitted_parameters, if: :devise_controller?
private
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys:[:username, :isPremium])
end
Now you can register the username and isPremium columns at the time of new registration.
With this, it is possible to manually switch the isPremium of the User model and divide it into attributes (such as providing a check box at the time of registration?), But this time I will try to make it a mechanism to automatically switch by link. So create and route the controller (skip if you're already done).
console
rails g devise:controllers users
config/routes.rb
devise_for :users,
controllers: {
registrations: 'users/registrations'
}
After that, paste the link wherever you like (this time it will be home / index). At that time, I will make it possible to pass parameters and divide the attributes.
erb:home/index.html.erb
<%= link_to "Login", new_user_session_path %>
<%= link_to "Member registration", new_user_registration_path(premium: "false") %>
Premium membership registration<%= link_to "Here", new_user_registration_path(premium: "true") %>
Both membership registration and premium membership registration have the same "new_user_registration_path", but we pass a variable called premium to differentiate them.
In "new_user_registration_path", the new action of RegistrationsController of users created earlier should be called, so I will write it.
users/registrations_controller.rb
# GET /resource/sign_up
def new
@premium = params[:premium] #add to
super
end
Uncomment the new action (#) and put the premium you just passed into @premium. (Here I wrote @premium = params [: premium] after super and got hooked for an hour.)
Since it is not necessary to display it in View, use f.hidden_field etc. (other forms are omitted).
erb:registrations/new.html.erb
<%= f.hidden_field :isPremium, :value => @premium %>
If you write this in an appropriate place in the form, @premium passed from the link will be registered in the isPremium column of the User model.
I made it for the time being, but I don't feel like I'm taking a detour. After that, I was worried because I had little understanding of Rails and called super first with the new action of registrations. Please let me know if there is a smarter way!