ActiveRecord - has_many:through,:dependent => :destroy sql不正确

时间:2012-03-28 15:43:07

标签: ruby-on-rails activerecord many-to-many

我正在尝试“反缓存”每个标签中的帖子数量。后保存回调正在工作,但后毁灭不是。看起来像破坏sql是不正确的。

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

测试失败

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

正确的sql应该是

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

3 个答案:

答案 0 :(得分:1)

我遇到了完全相同的问题,我的修复方法是在连接表中添加主键列(在您的情况下为PostTag)。

似乎rails需要主键才能使:dependent => :destroy选项起作用。

答案 1 :(得分:0)

我建议使用单独的递增/递减功能而不使用count + save。这应该能够正常运行,表现良好,不会触发对标签的副作用,也不会在竞争条件下弄乱你的计数。

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

答案 2 :(得分:0)

可能是因为你使用过的模型

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

而不是

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