How to Add Custom Attributes to a Devise Based Authentication System
Learn how to customize the Devise authentication system by adding new User attributes that can be added during the sign up process.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

Starting in the pivotal tracker project management dashboard, you can see the next item on the list is to customize our attributes. What I mean by that is we want the ability for our user to have a name instead of simply going by their e-mail address. I think it makes sense for them also to be able to type their name out.

If we come back to the site and click on register, you can see by default devise only gives us the ability to have an email address and a password. That is what we're going to change.

medium

If you remember back to when we created the migration, we scroll down, you can see that we added a name attribute. Even though we added it in the migration, that doesn't automatically add it to the form fields. We're going to start off by doing that.

I have opened up our items right here so we have views/devise/registrations you can see that we have two files here. Open up both of them (devise/registrations/edit.html.erb and devise/registrations/new.html.erb) and I'll put them right next to each other.

Go to View and then go to layout and select columns. I'm going to have edit right here and new right here.

All we have to do is actually create these fields and I'm going to also show you what it does. In fact before I save this let me show you what edit does.

Right here (edit.html.erb lines 12 and 13) I'm going to change email to name. I also want to change this to textfield and get rid of auto focus true. We don't want this exactly like the email address. If you're curious what this does, if you click on sign up, notice how the cursor is automatically in the little e-mail field. That's because it has auto focus true set on it. You can only have one field to have auto focus true when you load the page by default.

large

Usually this is kind of what you want is to have it on the e-mail address, it makes a little bit easier for the user to simply start typing instead of having to click in it. That's a reason why I removed it from name. I also remove this so it's not using the email field type. This just gives some kind of little validation. If a user starts typing something in and it's not a valid email address then it is going to throw an error.

This is just for the HTML5 client validation. I talked about how in the configuration file it had all those validations for the e-mail address, this is different than that. This is just the little form field, not the server side validation.

With that being said, we do want to have a text field here for name and that's it for the edit side.

Now come to the new.html.erb, this is actually the registration page. If you ever want to test it out, you can just come here up to the top hit save up some jibberish right there. Hit refresh and you can see that this is the page that we are working on. Delete that and right below here I'm going to paste in what I copied from the page.

large

Hit save and now if I refresh, you can see that now we have a name value. This by itself is not going to work just as it is and I'll show you because if I create a new account. test2@test.com I can type in my name and password and then hit sign up.

You can see "Welcome! You have signed up successfully." which you may think that worked, however it did not.

For one thing, the name value is blank right here.

large

It didn't capture the name, go to the terminal and look at the actual sql code. It selected one, it inserted two users, the e-mail address and the created at values but it didn't do the name. If you scroll up just a little bit right here you can see it created a post request. That's the route that it uses whenever it wants to create something, this is the point right where is said "OK, we're creating a new user and we're going to use the devise registration controller create and we're going to pass in these parameters.

It passed in the type, passed in an authenticity token, which is something we'll talk about later, and then it passed in this user object. This is what we're concerned with, it passed in the user it said "Here is his e-mail addresses test2@test.com, so far so good, it passed in the name just like I typed it in and then it passed in the password would you notice it filters it doesn't show this even in the log files for security reasons. And that was it.

The name didn't get passed in. The reason is because of this one line right here, it says "Unpermitted parameter name."

large

If you remember to back to when we talked about our controllers, let's open up for review, the blog controller. If you scroll all the way down do you remember when I talked about the blog params and talked about how the title and body right here are items that we have to list off and what they're telling rails is these are the attributes that can be passed in. But these are the only attributes that can be passed in. You can not submit anything besides these two items in the form or else we're going to think that it might be a hacker that's trying to send some other bad parameter. They're trying to send some bad data. So white listing this is very important. That is what is happening right here.

If I open up the terminal and you see unpermitted parameter, this means that it needs to be told that name can be passed in the form. Whenever we're doing this with devise it's not quite as easy as when we're doing it just with a regular controller because we don't have access to the devise controller directly.

If you come to your list of controllers you may notice one of the things that was not created for us was a devise or a user controller. We have our application controller, blogs, pages and portfolios but not actually one for our users. That is what we're going to fix in order to get this working.

Let's open up the application controller. This is the controller, we're going to talk a lot more about this when we get into our controller section, it is essentially the master controller for the entire app. If you click on blog controller you can see that blog controller actually inherits from ApplicationController and so it pages and so does portfolios.

If you remember your ruby inheritance, what this means, all of these controllers inherit from it. They are going to have access to anything that you put inside of ApplicationControl. This is where we're going to start by putting our special devise parameter whitelist. In the next guide, I'm going to show you how we can refactor this and follow best practices because this is something I've spoken about with a number of developers. No one likes putting their devise whitelist in the application controller but it's something that's been done for years. I'm going to show you what I personally do and what I think is considered a better practice.

What I'm going to do here (application_controller.rb) is I'm going to add a before filter. Remember that if you look at any of our let's take a look at our blog controller, we have a before action. (before action and before filter are pretty similar) What they're essentially doing is they're saying that whatever happens before everything else, that is what I want to tell it to do. Whatever method I pass in I'm saying run this before you run everything else in the rest of the controller. Since this is the application controller we're saying run whatever I say here run this before all of the other controllers.

I'm going to say before_filter :configure_permitted_parameters. if: :devise_controller?. The question mark is a special method here that is going to check and say I want you to run this. I want you to run this method but only if you're receiving some type of devise control or communication.

We're not have to worry about this running all the time even though it's in our application controller because I can put this flag at the end of it. It's not a big deal on that side of it. Right now we're going to get more into all of this when we get in the controllers section. For right now just know that we are essentially just saying I want to add and create a method and have it run any time you're communicating with a device.

Now we can instantiate this method. Here I am going to create a method called configure permitted parameters and this is what's going to be called. Inside of it I have some new things that I need to put in. Now these are specific to rails 5. So if you have come from rails 3 or rails 4 there are some new methods that devise came up with and those old ones that you're using will no longer work.

If I do devise_parameter_sanitizer.permit and then pass in sign up and then pass in the keys that I want to permit, I don't have to pass in e-mail, password and all of those because devise's own system already has that. I just need to add on to the ones that I want to add, in this case it's just name.

I'm going to copy this because this is for our registration route. We also need to do it for our editing route. I'm going to say account update because that's actually the name that devise uses. This one is also going to be key's name.

large

If I hit save, let's come back to our page. Click log out and let's do this from scratch as a test.

I'm going to say test3@test.com and save just the name of Jordan and pass in a password. Click sign up and let's test this out.

I come to edit right here you can see that now that's working.

large

Now it says Jordan, if I update this to say "Jordan Hudgens" (whenever you're making a edit on the user you also have to type in the user's password is to confirm the change) hit update, and there you go.

So now we're good to go, if I come up hit edit just verify one more time, you can see it has been updated to Jordan Hudgens. If I change it include my middle name, Jordan David Hudgens, hit update.

We can check out the controller and now look if you see where all of this happens where you have the put request. Now it says the parameters when you see the user object it says test3@test.com name Jordan David Hudgens and we no longer have that unpermitted parameter list

large

Let's see all the changes we made, we made a change to the application controller, the registration controller for editing and for creating a new log in.

  • git status
  • git add .
  • git commit -m "Added new parameters for user registration and editing account."
  • git push origin authentication

Very nice going through that! In the next guide we're going to implement some best practices so we can clean up our application controller and we're going to use controller concerns in order to do it. So I'll see you then.

Resources