validations rails example create callbacks before_update before association after_save after_create after ruby-on-rails ruby model attributes callback

ruby on rails - rails - Rieles: actualice el atributo de modelo sin invocar devoluciones de llamada



rails before_update (9)

Algunas opciones de cómo hacer esto en rails4 http://edgeguides.rubyonrails.org/active_record_callbacks.html#skipping-callbacks

Tengo un modelo de usuario que tiene un atributo: credits. Quiero un botón simple que agregará 5 a los créditos del usuario, a través de una ruta llamada "agregar" para que / users / 3 / add agregue 5 a los créditos de id de usuario = 3.

def add @user = User.find(params[:id]) @user.credits += 5 redirect_to root_path end

Esa es la parte relevante de mi controlador. El problema es que no quiero llamar a @ user.save porque tengo una devolución de llamada before_save que vuelve a encriptar la contraseña del usuario en función de la hora UTC actual. Simplemente quiero agregar 5 al atributo y evitar la devolución de llamada, nunca pensé que una cosa tan simple pudiera ser tan difícil.

EDITAR:

Cambié la devolución de llamada a: before_create, aquí está mi nuevo código de controlador (parte relevante):

def add @user = User.find(params[:id]) @user.add_credits(5) @user.save flash[:success] = "Credits added!" redirect_to root_path end

y aquí está mi código en el modelo:

def add_credits(num) self.credits = num end

EDICION 2:

Ok, fue un problema de validación que hizo que los cambios en "EDITAR" no funcionaran, ¡pero aún me encantaría una respuesta a la pregunta original de actualización sin devoluciones de llamada!


Como respuesta general, en Rails 4 esta es una manera simple de actualizar atributos sin activar devoluciones de llamada:

@user.update_column ''credits'', 5

Si necesita actualizar múltiples atributos sin devoluciones de llamada de triggers:

@user.update_columns credits: 5, bankrupt: false

Aquí hay otras opciones http://edgeguides.rubyonrails.org/active_record_callbacks.html#skipping-callbacks si lo prefiere, pero me pareció que esta era la más fácil.


Creo que deberías usar el método update_counters en este caso. Úselo así en su acción de controlador:

def add User.update_counters params[:id], :credits => 5 redirect_to root_path end


Debería poder usar update_all para evitar la activación de devoluciones de llamada.

def add @user = User.find(params[:id]) User.where(:id=>@user.id).update_all(:credits => @user.credits+5) redirect_to root_path end

Preferiría poner esta lógica en el modelo, pero esto debería funcionar para resolver su problema original como se especifica en el controlador.


Para actualizar múltiples atributos sin devolución de llamada, puede usar update_all en su modelo de la siguiente manera:

self.class.update_all({name: value, name: value}, self.class.primary_key => id)

Si realmente lo deseas, incluso puedes probar un método update_columns y mezclar esto con tu clase base de registro activo.

Para actualizar un atributo, puede usar update_column. Además, hay algunos métodos específicos que se pueden encontrar en las guías de rieles http://guides.rubyonrails.org/active_record_callbacks.html#skipping-callbacks




Tal vez su otro hook before_save debería verificar si la contraseña del usuario realmente ha cambiado antes de encriptarla nuevamente.


Usted tiene una cantidad de opciones, que incluyen cambiar la devolución de llamada que usa, por ejemplo, after_create .

Puede actualizar las columnas sin activar las devoluciones de llamada; consulte http://guides.rubyonrails.org/active_record_callbacks.html#skipping-callbacks devoluciones de http://guides.rubyonrails.org/active_record_callbacks.html#skipping-callbacks en la guía de AR. Por ejemplo, update_column no update_column devoluciones de llamada. El enlace anterior enumera las funciones no desencadenantes.

También puede usar cualquiera de los formularios de devolución de llamada condicional (o incluso un observador) para cuando se cambie la contraseña. Ver ActiveModel::Dirty , eg, @user.password_changed? .