2012-03-28 9 views
5

Sto provando a "contrastare la cache" del numero di post in ogni tag. Il callback dopo il salvataggio funziona ma il dopo destroy non lo è. Sembra che distruggere sql non sia corretto.ActiveRecord - has_many: through,: dependent =>: destroy sql non è corretto

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 

Il test fallisce

# @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 

la correttezza sql dovrebbe essere

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

Provare a utilizzare set_table_name anziché table_name =? Penso che il metodo set_table_name cambi alcune altre cose. –

+0

@joe Pym Che non ha funzionato. Inoltre, set_table_name è ora deprecato. -> AVVISO DI AVVISO: la chiamata a set_table_name è deprecata. Utilizza invece 'self.table_name = 'the_name''. – Marcelo

+1

Ho riscontrato un errore molto simile nella mia situazione. Anch'io vorrei una risposta. – user1149547

risposta

0

Io suggerirei di funzioni di incremento/decremento separate e non si utilizza conteggio + salvare. Questo dovrebbe funzionare correttamente, comportarsi bene, non innescare effetti collaterali su Tag e non rovinare il conteggio in condizioni di gara.

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

può essere perché nei modelli che hai utilizzato

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

invece di

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

?

1

Avevo lo stesso identico problema, la soluzione per me era aggiungere una colonna di chiave primaria alla tabella di join (PostTag nel tuo caso).

Sembra che le guide abbiano bisogno di una chiave primaria per l'opzione :dependent => :destroy per funzionare.

+0

Grazie, non so di OP ma questo ha funzionato per me. Per ': dependent =>: destroy' Rails non esegue' WHERE foreign_key = smth' come ci si aspetterebbe, recupera i bambini e quindi esegue 'WHERE id = smth' per ognuno. – yefrem

Problemi correlati