2011-02-05 32 views
6

Ahora me doy cuenta de que este tema ya se ha cubierto muchas veces. Sin embargo, no parecía haber una solución que deseara eximir el campo de contraseña actual solo cuando la contraseña en la base de datos estuviera en blanco.Ruby on Rails, gema de Devise. ¿Cómo eliminar la contraseña actual cuando la contraseña está en blanco?

tengo actualmente requiere la contraseña en mi modelo de usuario como:

def password_required? 
    (authentications.empty? || !password.blank?) && super 
end 

Entonces copiar la función de actualización a través en mi controlador de inscripciones:

def update 
    if resource.update_with_password(params[resource_name]) 
    set_flash_message :notice, :updated 
    sign_in resource_name, resource, :bypass => true 
    redirect_to after_update_path_for(resource) 
    else 
    clean_up_passwords(resource) 
    render_with_scope :edit 
    end 
end 

yo sólo no saben cómo Asegurándome de que el dispositivo no necesita una contraseña al editar una contraseña en blanco, ¿también necesito eliminar el campo de contraseña actual de la vista y hacer esto?

<% if current_user.password_required? %> 
    <p><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br /> 
    <%= f.password_field :current_password %></p> 
<% end %> 
<p><%= f.submit "Update" %></p> 

Cualquier sugerencia sería muy bien en esto como estoy seguro de que se me escapa algo, pero yo todavía soy nuevo en rieles en su conjunto. ¡Gracias!

Respuesta

8

¡Bien, así que finalmente me he dado cuenta de esto!

Añadir lo siguiente a su clase RegistrationsController < Diseñar :: RegistrationsController

def update 
    if resource.update_with_password(params[resource_name]) 
    set_flash_message :notice, :updated 
    sign_in resource_name, resource, :bypass => true 
    redirect_to after_update_path_for(resource) 
    else 
    clean_up_passwords(resource) 
    render_with_scope :edit 
    end 
end 

A continuación, el siguiente a su modelo de usuario:

def update_with_password(params={}) 
    current_password = params.delete(:current_password) if !params[:current_password].blank? 

    if params[:password].blank? 
    params.delete(:password) 
    params.delete(:password_confirmation) if params[:password_confirmation].blank? 
    end 

    result = if has_no_password? || valid_password?(current_password) 
    update_attributes(params) 
    else 
    self.errors.add(:current_password, current_password.blank? ? :blank : :invalid) 
    self.attributes = params 
    false 
    end 

    clean_up_passwords 
    result 
end 

def has_no_password? 
    self.encrypted_password.blank? 
end 

Lo único que estaba un poco confundido acerca es que en el vista de edición:

<% if !current_user.has_no_password? %> 

Lo envolví en que si, yo habría pensado que habría sido:

<% if current_user.has_no_password? %> 

Si alguien puede ver nada para mejorar mi código o de una manera diferente, más eficiente, hágamelo saber!

+1

'' devuelve 'current_user.has_no_password true' si no hay una contraseña, por lo tanto el if la instrucción ejecuta su bloque. Está utilizando un lenguaje negativo para validar esa afirmación ... debe escribir 'a menos que current_user.has_no_password?', Pero aún así es gracioso. Es una lectura más fácil si lo haces 'current_user.has_password?' Y establecer la definición para devolver 'self.encrypted_password.present?' (Me doy cuenta de que esto se ha discutido a continuación, pero esto pertenece a los comentarios, y he dado un alternativo , solución más legible) – wulftone

+0

Utilicé esto como la base de otra cosa y funciona bastante bien.Solo cambio: tuve que eliminar 'if! Params [: current_password] .blank?' Para evitar errores en la asignación masiva, porque la contraseña actual se estaba configurando en '" "' (y por lo tanto 'blank? == true') así que no fue borrado de params, y luego 'update_attributes (params)' intentó actualizar el registro del usuario con ': current_password =>" "' - obviamente falla ya que 'current_password' no es un atributo del usuario ... Maybe Aunque tengo el lado equivocado del palo? Además, ¿el 'yo 'no es redundante? – dgmstuart

+0

Probé esta solución, obtuve No puedo asignar en masa los atributos protegidos: contraseña_actual – simo

3

Otro cambio muy leve al requerir el campo de contraseña actual o no: mi objetivo nunca es requerir una contraseña actual a menos que estén actualizando su contraseña. para las cuentas de Oauth, verifico el id de Facebook en la vista, y no mostrar los campos de contraseña en absoluto.

En el controlador de inscripciones:

Users::RegistrationsController < Devise::RegistrationsController 

def update 

self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key) 

    if resource.update_with_password(params[resource_name]) 
    set_flash_message :notice, :updated if is_navigational_format? 
    sign_in resource_name, resource, :bypass => true 
    respond_with resource, :location => after_update_path_for(resource) 
    else 
    clean_up_passwords(resource) 
    respond_with_navigational(resource){ render_with_scope :edit } 
    end 


end 

En User.rb, utilizo update_with_password, y luego llamo verify_password_and_update sólo si el usuario ha introducido algo en el campo de la contraseña de la vista. De lo contrario, puedo borrar el parámetro contraseña actual y llamo update_without_password (este método se basa en idear ahora también):?

#to remove the current password check if updating a profile originally gotten via oauth (fb, twitter) 


    def update_with_password(params={}) 
    if params[:password].blank? 
     params.delete(:current_password) 
     self.update_without_password(params) 
    else 
     self.verify_password_and_update(params) 
    end 
    end 

    def update_without_password(params={}) 

    params.delete(:password) 
    params.delete(:password_confirmation) 
    result = update_attributes(params) 
    clean_up_passwords 
    result 
    end 
    def verify_password_and_update(params) 
    #devises' update_with_password 
    # https://github.com/plataformatec/devise/blob/master/lib/devise/models/database_authenticatable.rb 
    current_password = params.delete(:current_password) 

    if params[:password].blank? 
     params.delete(:password) 
     params.delete(:password_confirmation) if params[:password_confirmation].blank? 
    end 

    result = if valid_password?(current_password) 
     update_attributes(params) 
    else 
     self.attributes = params 
     self.valid? 
     self.errors.add(:current_password, current_password.blank? ? :blank : :invalid) 
     false 
    end 

    clean_up_passwords 
    result 
    end 
+0

muchas gracias por compartir su código. me quedé atrapado haciendo esto por un tiempo y ver su código ayudó =) – Sasha

+0

no hubo problema, ¡me alegro de que me ayudó! – Danny

Cuestiones relacionadas