2011-04-25 14 views
13

Quiero crear un método after_save para mi acción de velocidad. Se dividiría rating_score/ratings y actualizará la calificación de la columna.¿Rails cómo actualizar una columna después de guardar?

class KonkurrancersController < ApplicationController 
    def rate 
    @konkurrancer = Konkurrancer.find(params[:id]) 
    @container = "Konkurrancer"[email protected]_s 

    @konkurrancer.rating_score += params[:vind][:rating].to_i 
    @konkurrancer.ratings += 1 
    @konkurrancer.save 

    respond_to do |format| 
     format.js 
    end 
    end 
end 

Esta es mi modelo:

class Konkurrancer < ActiveRecord::Base 
    after_save :do_foobar 

    private 
    def do_foobar 

     rating_score = self.rating_score 
     ratings = self.ratings 
     rating = (rating_score/ratings) 
     self.update_attributes(:rating => rating) 

    end 
end 

Mis carriles de registro:

Started POST "/konkurrancers/rate/46" for 127.0.0.1 at 2011-04-26 23:40:56 +0200 

    Processing by KonkurrancersController#rate as */* 
    Parameters: {"utf8"=>"Ô£ô", "authenticity_token"=>"MACFM37hX4S6XA9vryn7gtfl21P 
vcaPBSiKDI8mfurg=", "vind"=>{"rating"=>"4"}, "id"=>"46"} 
    ←[1m←[36mKonkurrancer Load (1.0ms)←[0m ←[1mSELECT `konkurrancers`.* FROM `kon 
kurrancers`←[0m 
    ←[1m←[35mCACHE (0.0ms)←[0m SELECT `konkurrancers`.* FROM `konkurrancers` 
    ←[1m←[36mCACHE (0.0ms)←[0m ←[1mSELECT `konkurrancers`.* FROM `konkurrancers`← 
[0m 
    ←[1m←[35mKonkurrancer Load (1.0ms)←[0m SELECT `konkurrancers`.* FROM `konkurr 
ancers` WHERE (`konkurrancers`.`cached_slug` = '46') LIMIT 1 
    ←[1m←[36mSQL (2.0ms)←[0m ←[1mSELECT sluggable_id FROM slugs WHERE ((slugs.slu 
ggable_type = 'Konkurrancer' AND slugs.name = '46' AND slugs.sequence = 1))←[0m 
    ←[1m←[35mKonkurrancer Load (1.0ms)←[0m SELECT `konkurrancers`.* FROM `konkurr 
ancers` WHERE (`konkurrancers`.`id` = 46) LIMIT 1 
    ←[1m←[36mSQL (0.0ms)←[0m ←[1mBEGIN←[0m 
    ←[1m←[35mLink Load (1.0ms)←[0m SELECT `links`.* FROM `links` WHERE (`links`.k 
onkurrancer_id = 46) LIMIT 1 
    ←[1m←[36mSQL (0.0ms)←[0m ←[1mROLLBACK←[0m 
Rendered konkurrancers/_rating.html.erb (1.0ms) 
Rendered konkurrancers/rate.js.erb (22.0ms) 
Completed 200 OK in 606ms (Views: 286.0ms | ActiveRecord: 6.0ms) 

Cómo debería crear esto?

+0

vea esto [devoluciones de llamada] (http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html) –

Respuesta

12

lo que quiere es una devolución de llamada. Puede crear una devolución de llamada after_save en su modelo Konkurrancer, que se activa después de llamar al método save() para ese modelo.

Por ejemplo:

class Konkurrancer < ActiveRecord::Base 
    after_save :do_foobar 

    private 
    def do_foobar 

     rating_score = self.rating_score 
     ratings = self.ratings 
     rating = (rating_score/ratings) 
     self.update_attributes(:ratings => rating) 

    end 
end 

[EDIT] Debe utilizar auto, ya que el modelo que se está editando es el propio modelo. Pruébelo y aplique la lógica/implementación necesaria.

Echa un vistazo a este guide para obtener más información.

Espero que ayude!

+0

¿Cómo me aseguro de que sea la columna de la derecha la que se actualice? –

+0

He actualizado mi respuesta –

+0

Actualicé mi respuesta, con un bloque de código de ejemplo que supuestamente resalta su problema. Modifícalo según tus necesidades. –

0
@konkurrancer.update_attributes :ratings=>'updated value' 
+0

agregue este código después de guardar la devolución de llamada – Naveed

52

Cualquier update_attribute en una devolución de llamada after_save hará que la recursividad, en Rails3 +. Lo que debe hacerse es:

after_save :updater 
# Awesome Ruby code 
# ... 
# ... 

private 

    def updater 
    self.update_column(:column_name, new_value) # This will skip validation gracefully. 
    end 
7

No sé por qué la gente está Upvoting la respuesta equivocada y downvoting la respuesta correcta.

Zakelfassi tiene razón y Christian Fazzini se equivoca con Rails 3 y superiores. Si haces #update_attributes en una devolución de llamada guardada, entrarás en una recurrencia infinita. Desea hacer #update_column según su ejemplo.

Pruébalo y verás.

+1

los upvotes me confundieron tanto que fui y verifiqué la fuente de Rails, compruebo exhaustivamente mi código, solo para estar 100% seguro ... – zakelfassi

+0

Sí, solo puedo suponer que son usando una versión anterior de Rails. –

+0

Tenga en cuenta que la pregunta original y la respuesta aceptada de Christian Fazzini son ambos de 2011. La versión de Rails es casi con certeza 2.x. – joanwolk

Cuestiones relacionadas