Usando la gema brazuca devise para autentificacación en Rails 4, sucede que además del mail y el pass, hay otros atributos que necesito guardar en la tabla users.

protected attributes

En Rails < 4 para ello bastaba con declararlos como attr_accessible >>, lo cual había hecho el desarrollador cuyo pato estoy pagando y para lo cual -sospecho- está importando la gema de esta funcionalidad deprecada
Gemfile:

gem 'protected_attributes'

user.rb:

class User < ActiveRecord::Base
    devise :registerable#etc
    attr_accessible :email, :password, :nombre, :largo_del_pelo #etc
end

strong parameters

Como dije, attr_accessible fue deprecado en Rails 4 y ahora el filtro se hace a nivel del controlador, ésto es lo que se llama strong parameters. ¿Qué tiene que ver? Pues siga leyendo:

Con un poco de debug, vemos que el hash del que se arman los usuarios es sign_up_params

class Devise::RegistrationsController < DeviseController
#...
# POST /resource
  def create
    self.resource = build_resource(sign_up_params)
    if resource.save
#....
end

los cuales no incluyen mis atributos

{"email"=>"1@example.com",
"password"=>"password",
"password_confirmation"=>"password"}

porque están ‘sanitizados’

def sign_up_params
  devise_parameter_sanitizer.for(:sign_up)
end

Nótese que ésto es nuevo en el branch rails4, por lo que por aquí va la cosa, vea a continuación:
Este método está definido en lib/devise/controllers/helpers.rb, y soporta Strong Parameters

# Setup a param sanitizer to filter parameters using strong_parameters. See
# lib/devise/controllers/parameter_sanitizer.rb for more info. Override this
# method in your application controller to use your own parameter sanitizer.
def devise_parameter_sanitizer
  @devise_parameter_sanitizer ||= if defined?(ActionController::StrongParameters)
    Devise::ParameterSanitizer.new(resource_class, resource_name, params)
  else
    Devise::BaseSanitizer.new(resource_class, resource_name, params)
  end
end

Y he ahí la clave

Override this method in your application controller to use your own parameter sanitizer

i.e. el filtro lo está haciendo esta clase BaseSanitizer, y debo sobrescribirlo.

sobrescritura

Primero entenderlo un poco.. no me meteré en el método for, pero éste invoca a sign_up, como vimos, el cual tiene información decidora

def sign_up
  default_params.permit(auth_keys + [:password, :password_confirmation])
end

por tanto la primera tentación es añadir mis atributos simplemente en devise.rb (en mi app)

config.authentication_keys = [ :email , :nombre, :largo_de_pelo ]

con lo cual efectivamente los atributos se guardan pero, evidentemente, no me puedo loguear: tendría que hacer que el usuario escribiera estos atributos para ingresar.

Por tanto tendré que sobrescribir. Lo intentaré con el mismo método sign_up_params, el cual se encuentra en la misma clase de la que ya estoy heredando

class Users::RegistrationsController < Devise::RegistrationsController
#etc
  protected
  def sign_up_params
    params.require(:user).permit(:email, :password, :password_confirmation, :nombre, :largo_de_pelo)
  end
#...
end

y funciona 🙂

Véase mi respuesta en Stack Overflow >>

Este sitio utiliza cookies.    Leer más