Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby Build a Simple Ruby on Rails Application Writing Tests Validating Presence

validates :first_name, presence: true not working

class User < ActiveRecord::Base # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable

validates :first_name, presence: true

validates :last_name, presence: true

def full_name
    first_name + "" + last_name
end

end

That is the current code in my user.rb model file. When I test the application on my server even if i enter a first name the error "First name can't be blank" appears, I cant see why this is a problem as the first_name and last_name field are in my schema.rb file. can anyone shed some light?

8 Answers

Maciej Czuchnowski
Maciej Czuchnowski
36,441 Points

Yeah, validation is fine. The thing that changed and that causes most problems was the handling of mass assignments. In Rails 3 it was enough to make an attribute accessible in the model (using attr_accessible). This by default created getters and setters for those attributes and was easy. In Rails 4, Strong Parameters were introduced, which change the way you allow attributes to be entered through forms. This was moved to controllers and made things more complicated when you're using Devise.

To get this immediate problem out of the way, I will give you my recipe which I use in my every project nowadays. It's clean and effective and the credit goes to railsapps.org. Go to your application folder and create a file in config/initializers folder. Name it whatever you want with .rb extension. I always name it devise_permitted_parameters.rb. So it's config/initializers/devise_permitted_parameters.rb. And its contents would look like this in your app:

module DevisePermittedParameters
  extend ActiveSupport::Concern

  included do
    before_filter :configure_permitted_parameters
  end

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) << :first_name << :last_name
    devise_parameter_sanitizer.for(:account_update) << :first_name << :last_name
  end

end

DeviseController.send :include, DevisePermittedParameters

If you add more attributes to the user model in the future, just add more "<< :attribute_name" thingies. Now your first and last name should work properly when signing up and editing user info. This only applies to models generated by devise (user in your case). You will also have to learn how to handle mass assignments in all the other, 'standard' models. Fortunately, this boils down to adding one method to every controller. Read as much as you can about "Strong Parameters" and learn how to use them, because it's now standard in Rails 4+. If you'll have any problems or questions, don't hesitate to ask. Hope this helps.

Michelle Cannito
Michelle Cannito
8,992 Points

I had the same problem and kept searching. Code for the application_controller.rb:

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:first_name, 
        :last_name, :profile_name, :email, :password, :password_confirmation) }
  end

Forgot what other files to change. As stated above, attr_acessible not enough for sharing variables in Rails 4. My user name on github is jazzminjoy, and all is public. I completed the project. See statbook, not treebook, and odot too.

Maciej Czuchnowski
Maciej Czuchnowski
36,441 Points

Yeah, this is basically the same thing, just inserted into the app controller ;). But I see that you only have sign_up sanitizer. Does updating work for you if you're trying to chnange the first name or last name?

Maciej Czuchnowski
Maciej Czuchnowski
36,441 Points

Look at your Gemfile and tell me what version of Rails you're using.

I'm using gem 'rails', '4.1.4'

I'm currently running html validations for requiring all text inputs as well as a javascript validation script however I feel that its safer to also have a server side validation

Maciej Czuchnowski
Maciej Czuchnowski
36,441 Points

OK, since this course was made in Rails 3, some things have changed in Rails 4 and this causes a lot of confusion for Treehouse users. I assume that parameters such as first_name and last_name are not being saved into the database because of the way Rails 4 handles mass assignments (if I'm wrong and you properly sanitized those attributes, then ignore me). You have two choices: start the app from scratch using the same version of Rails they are using in the videos OR read about the differences and try to translate things done in the course into Rails 4 way. The second choice is obviously harder :). Let me know which way you want to go and I can instruct you on how to start.

I think I'd rather try to translate what is going on in the course to the rails 4 way. Where would I start? the rails documentation read that validates :first_name, presence: true is the proper format for validation

Awesome I'll definitely read up on strong parameters, that was a lot of help. Now back to developing!

Unfortunately it doesn't actually work. Im wondering in this method:
def configure_permitted_parameters devise_parameter_sanitizer.for(:sign_up) << :first_name << :last_name devise_parameter_sanitizer.for(:account_update) << :first_name << :last_name end

if :sign_up should be the name of the path i am reffering to in the form, ie; the registration_path

Maciej Czuchnowski
Maciej Czuchnowski
36,441 Points

OK, can you deploy the project on github so I could take a look at the more general picture?