2012-03-28 11 views
5

Estoy tratando de "contabilizar en caché" el número de publicaciones en cada etiqueta. La devolución de llamada después de guardar funciona pero la destrucción posterior no. Parece que destruir sql no es correcto.ActiveRecord - has_many: through,: dependent =>: destroy sql no es correcto

class Post < ActiveRecord::Base 
    has_many :post_tags, :dependent => :destroy 
    has_many :tags, :through => :post_tags 
end 

class Tag < ActiveRecord::Base 
    has_many :post_tags, :dependent => :destroy 
    has_many :posts, :through => :post_tags 
end 

class PostTag < ActiveRecord::Base 
    self.table_name = :posts_tags 
    belongs_to :post 
    belongs_to :tag 

    after_save :update_tag_posts_count 
    after_destroy :update_tag_posts_count 

    def update_tag_posts_count 
    tag.posts_count = tag.posts.count 
    tag.save 
    end 
end 

La prueba falla

# @tag.posts_count == 10 
Failure/Error: @tag.posts.first.destroy 
ActiveRecord::StatementInvalid: 
Mysql2::Error: Unknown column 'posts_tags.' in 'where clause': DELETE FROM `posts_tags` WHERE `posts_tags`.`` = NULL 

El SQL correcta debería ser

DELETE FROM `posts_tags` WHERE `posts_tags`.`post_id` = {the post id} 
+0

¿Intenta usar set_table_name en lugar de table_name =? Creo que el método set_table_name cambia algunas cosas más. –

+0

@joe Pym Eso no funcionó. Además, set_table_name ahora está en desuso. -> ADVERTENCIA DE DEPRESIÓN: la llamada a set_table_name está en desuso. Por favor usa 'self.table_name = 'the_name'' en su lugar. – Marcelo

+1

Recibo un error muy similar en mi situación. A mí también me gustaría una respuesta. – user1149547

Respuesta

0

me gustaría sugerir funciones de incremento/decremento separados y no mediante recuento + guardar. Esto debería funcionar correctamente, funcionar bien, no desencadenar efectos secundarios en Tag, y no estropear su conteo en condiciones de carrera.

class PostTag < ActiveRecord::Base 

    belongs_to :post 
    belongs_to :tag 

    after_create :increment_tag_posts_counter 
    after_destroy :decrement_tag_posts_counter 

    private 

    def increment_tag_posts_counter 
    Tag.increment_counter :posts_count, post_id 
    end 

    def decrement_tag_posts_counter 
    Tag.decrement_counter :posts_count, post_id 
    end 
end 
0

puede deberse a que en los modelos que utilizó

#post.rb 
has_many :post_tags, :dependent => :destroy 
#tag.rb 
has_many :post_tags, :dependent => :destroy 

en lugar de

#post.rb 
has_many :posts_tags, :dependent => :destroy 
#tag.rb 
has_many :posts_tags, :dependent => :destroy 

?

1

Tuve exactamente el mismo problema, la solución para mí fue agregar una columna de clave principal a la tabla de unión (PostTag en su caso).

Parece que los rieles necesitan una clave principal para que la opción :dependent => :destroy funcione.

+0

Gracias, no sé acerca de OP, pero esto funcionó para mí. Para ': dependent =>: destroy' Rails no ejecuta' WHERE foreign_key = smth' como cabría esperar, busca niños y luego ejecuta 'WHERE id = smth' para cada uno. – yefrem

Cuestiones relacionadas