简体   繁体   中英

Rails - how to validate presence of attribute AFTER creation

In my devise sign-up page, I have implemented an IP tracking feature that, when a user signs up, sends the country the user comes from, in order to populate the newly created account's attribute user_country .

I'd like to know if it's possible to implement a sort of validation on -user_country the same way I do for other User attributes ( email , password ...) when the user is created, to implement a sort of validation on user_country to be sure it's not empty nor nil, ie that a user must always have a country identified.

I can't use the classic way with validates :user_country, presence: true , because when the user is created the user_country is still not filled but WAITS that RegistrationController makes a call to geocoder this way => see the method on the bottom called 'after_sign_up_path_for'

/app/controllers/registrations_controller.rb

class RegistrationsController < Devise::RegistrationsController

  layout 'lightbox'

  def update     
    account_update_params = devise_parameter_sanitizer.sanitize(:account_update)

    # required for settings form to submit when password is left blank
    if account_update_params[:password].blank?
      account_update_params.delete("password")
      account_update_params.delete("password_confirmation")
    end    
    @user = User.find(current_user.id)
    if @user.update(account_update_params) # Rails 4 .update introduced with same effect as .update_attributes
      set_flash_message :notice, :updated
      # Sign in the user bypassing validation in case his password changed
      sign_in @user, :bypass => true
      redirect_to after_update_path_for(@user)
    else
      render "edit"
    end
  end

  # for Rails 4 Strong Parameters
  def resource_params
    params.require(:user).permit(:email, :password, :password_confirmation, :current_password, :user_country)
  end
  private :resource_params

  protected
    def after_sign_up_path_for(resource)
      resource.update(user_country: set_location_by_ip_lookup.country) #use concerns/CountrySetter loaded by ApplicationController
      root_path
    end  

end

Is there a way to implement a sort of 'validate' in this kind of situation?

My understanding is you want a User model to validate user_country field but only during steps after the initial creation?

class User
   validates_presence_of :user_country, on: :update
end

will only validate on update and not creation. See http://apidock.com/rails/ActiveRecord/Validations/ClassMethods/validates_presence_of for other options that you can add.

But for your use case, it seems odd that you need to do this in the controller after signup. I think it makes more sense to always validate user_country then inject the attribute during User creation in the controller.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM