0

I'm pretty new to Rails and I am trying to understand the way that Devise is treating the users resource and how the forms work.

Inside the app/views/devise/sessions/new.html.erb there is the following code (unmodified by me)

  <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
  <%= devise_error_messages! %>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true %>
  </div>

  <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
    <div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
  <% end %>

  <div class="field">
    <%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
    <%= f.password_field :password, autocomplete: "off" %>
    <% if @minimum_password_length %>
      <br />
      <em><%= @minimum_password_length %> characters minimum</em>
    <% end %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "off" %>
  </div>

  <div class="field">
    <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
    <%= f.password_field :current_password, autocomplete: "off" %>
  </div>

  <div class="actions">
    <%= f.submit "Update" %>
  </div>
<% end %>

And then in config/routes.rb there is the line

devise_for :users

Is this how devise knows what resource to use in the form? If I changed the config routes, would the form modify a different record in the DB on submit?

Ultimately I want to be able to modify other aspects of the user data which were added by me (e.g. user names). Could I just add additional form fields to this view and successfully modify those columns in users?

1 Answers1

1

Is this how devise knows what resource to use in the form? If I changed the config routes, would the form modify a different record in the DB on submit?

You can check those routes with the rake routes | grep devise command in your terminal. With the routes devise maps the controller#actions to the view, so that he knows for the action devise/session#new to use the view inside devise/sessions/new.html.erb and it will use the url /users/sign_in. Also routes differentiate between GET and PUT. When you call a new action, you will perform a GET Request and display a form. When you submit the form of login or signup (devise/sessions#create or devise/registrations#create) you will perform a put action. The record you modify or create depends on the controller action which performs a query in the database.

        new_user_session GET      /users/sign_in(.:format)                                    devise/sessions#new
            user_session POST     /users/sign_in(.:format)                                    devise/sessions#create
    destroy_user_session DELETE   /users/sign_out(.:format)                                   devise/sessions#destroy
       new_user_password GET      /users/password/new(.:format)                               devise/passwords#new
      edit_user_password GET      /users/password/edit(.:format)                              devise/passwords#edit
           user_password PATCH    /users/password(.:format)                                   devise/passwords#update
                         PUT      /users/password(.:format)                                   devise/passwords#update
                         POST     /users/password(.:format)                                   devise/passwords#create
   new_user_confirmation GET      /users/confirmation/new(.:format)                           devise/confirmations#new
       user_confirmation GET      /users/confirmation(.:format)                               devise/confirmations#show
                         POST     /users/confirmation(.:format)                               devise/confirmations#create

So inside the devise_controller that you can display in github https://github.com/plataformatec/devise/blob/master/app/controllers/devise/registrations_controller.rb or that you can generate in your app by executing rails generate devise:controllers [scope]. In this example inside the registrations#create devise will create a new user with the following code:

build_resource(sign_up_params)

which for my limited understanding of devise it is similar to doing:

@user = User.new(input_params)

Where input_params are the rails5 strong params. The type of user you register and where you do it depends on the input_params and on the model your are using. The model User will write to the users table in the db.

Devise http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions

Ultimately I want to be able to modify other aspects of the user data which were added by me (e.g. user names). Could I just add additional form fields to this view and successfully modify those columns in users?

Doing this is quite simple, you need in your app/controllers/application_controller.rb create the following method to add parameters to the devise strong params

def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:firstname, :lastname, :country, :location...])  
    devise_parameter_sanitizer.permit(:account_update, keys: [:firstname, :lastname, :country, :location...]) 
end  

You should create a migration to add those columns to the users table.

Then you need to edit the view devise/registrations/new.index.html, edit.index.html and all the other views.

For additional more detailed informations check the guides online or stackoverflow discussions.

How do I add additional fields to the Devise 'sign up' page?

Adding Fields To Devise Sign Up Using Rails 4

Community
  • 1
  • 1
Fabrizio Bertoglio
  • 5,890
  • 4
  • 16
  • 57
  • Wow, super informative and helpful, thank you! One question about strong params, should these be done via a before filter on application_controller.rb (e.g. `config_permitted_parameters` and a private method called the same)? – oneWorkingHeadphone Mar 13 '17 at 13:15
  • I did the above and it almost worked completely. The only additional thing I had to do was add an if to the before action so it reads: `before_action :configure_permitted_parameters, if: devise_controller?` Thank you again for a great explanation! – oneWorkingHeadphone Mar 13 '17 at 14:45
  • Glad it worked. I just read now, for any problem just ask me. Thanks. Fabrizio – Fabrizio Bertoglio Mar 13 '17 at 14:47