I'm new to rails (using rails 6), and I have a question that I didn't see answered on the site for my specific use case.
The basic scenario is the same as in many question - adding role based authentication to a rails application when using devise.
The way I implemented this was to create a roles table, and having a one to many relations between it and the users table.
I need only two users: guest and admin, and they have 1, 2 ids, respectively. I inserted the values into the roles table manually, using the rails console.
Now, I'm having trouble with the sign up form, which is the default one devise gem created:
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :password %>
<% if @minimum_password_length %>
<em>(<%= @minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
What I want to add is a select field that will show "admin" and "guest", and when the user submit the form, the right role_id will be added to the user record in the user table, but I don't get how to inform the devise view on the role table existence and how to match the string value of the role with the role id the I want the user to accualy have.
So my questions are:
How to add the roles to a select field in the devise sign up form?
How to handle after the user selects one of the roles string names, and match it with role id that will be added to the user when the form is processed?
I saw the following questions and many like them, but I didn't saw any of them dealing with matching string with id before the form is submitted:
how to automatically add a role to a user when signing up using devise
Adding Fields To Devise Sign Up Using Rails 4
Multiple models associated with devise user - fill in one model based on selection of role
If there is a question answering my issue, I'm sorry and I would be glad to get the link and close this question.
If there is any more info you need, please let me know.
Thanks!
Using an enum to differentiate admins from guests seems like the best option and will prevent you from having to complicate your model/form with unnecessary things like nested attributes.
Here's an example...
Create a role
column on the users table.
$ rails g migration add_role_to_users role:integer
In your migration file, make sure to set the default to 0.
add_column :users, :role, :integer, default: 0
Then, after migrating the db, in your User
model add the enum...
class User < ApplicationRecord
enum role: { guest: 0, admin: 1 }
...
end
Adding another role is as simple as adding a key/value to the role enum.
Then, in your devise form, you can add something like...
<%= f.label :role %>
<%= f.select :role, User.roles.keys %>
You will also need to make sure that you are adding role
as a permitted param...you seem to be adding it as a field in signup, so in ApplicationController
...
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
private
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:role])
end
end
If you go with this you will also have to remove your roles table and associations.