Ruby on rails 如何使列的最小值为0(或防止减量计数器设置负值)?

Ruby on rails 如何使列的最小值为0(或防止减量计数器设置负值)?,ruby-on-rails,Ruby On Rails,我有一个带有posts\u count列的标签模型,该列充当一个标签拥有的帖子数量的计数器缓存: schema.rb: t.integer "posts_count", :default => 0, :null => false def decrement_tag_counter_cache Tag.decrement_counter(:posts_count, self.tag.id) if !post.published? || post.decrement_ta

我有一个带有
posts\u count
列的标签模型,该列充当一个标签拥有的帖子数量的计数器缓存:

schema.rb:

 t.integer  "posts_count", :default => 0, :null => false
 def decrement_tag_counter_cache
    Tag.decrement_counter(:posts_count, self.tag.id) if !post.published? || post.decrement_tag_counters? 
  end
  after_save :increment_decrement_tag_counters # covers :save, :create, :update methods

  def increment_tag_counters? # if status changes and the previous status wasn't "Published"
    status_changed? && changed_attributes["status"] != "Published"
  end

  def decrement_tag_counters? # if status changes and the previous status was "Published"
    status_changed? && changed_attributes["status"] == "Published"
  end

  def increment_decrement_tag_counters
    if published? && increment_tag_counters?
      taggings.each { |tagging| tagging.increment_tag_counter_cache }
    elsif decrement_tag_counters?
      taggings.each { |tagging| tagging.decrement_tag_counter_cache }
    end
  end
标记。rb:

 t.integer  "posts_count", :default => 0, :null => false
 def decrement_tag_counter_cache
    Tag.decrement_counter(:posts_count, self.tag.id) if !post.published? || post.decrement_tag_counters? 
  end
  after_save :increment_decrement_tag_counters # covers :save, :create, :update methods

  def increment_tag_counters? # if status changes and the previous status wasn't "Published"
    status_changed? && changed_attributes["status"] != "Published"
  end

  def decrement_tag_counters? # if status changes and the previous status was "Published"
    status_changed? && changed_attributes["status"] == "Published"
  end

  def increment_decrement_tag_counters
    if published? && increment_tag_counters?
      taggings.each { |tagging| tagging.increment_tag_counter_cache }
    elsif decrement_tag_counters?
      taggings.each { |tagging| tagging.decrement_tag_counter_cache }
    end
  end
post.rb:

 t.integer  "posts_count", :default => 0, :null => false
 def decrement_tag_counter_cache
    Tag.decrement_counter(:posts_count, self.tag.id) if !post.published? || post.decrement_tag_counters? 
  end
  after_save :increment_decrement_tag_counters # covers :save, :create, :update methods

  def increment_tag_counters? # if status changes and the previous status wasn't "Published"
    status_changed? && changed_attributes["status"] != "Published"
  end

  def decrement_tag_counters? # if status changes and the previous status was "Published"
    status_changed? && changed_attributes["status"] == "Published"
  end

  def increment_decrement_tag_counters
    if published? && increment_tag_counters?
      taggings.each { |tagging| tagging.increment_tag_counter_cache }
    elsif decrement_tag_counters?
      taggings.each { |tagging| tagging.decrement_tag_counter_cache }
    end
  end
现在的问题是,有时,
递减\u标记\u计数器\u缓存
方法会使
posts\u计数
变为负值(例如-1)

有没有办法告诉Rails:将
posts\u count的最小值设为0?因此,如果当前值为0且计数器递减,
posts\u count
仍将保持为0?我可以做的另一件事是防止
递减计数器设置负值。可能吗


(这不应该作为验证工作,而是作为默认行为,因为我不希望出现错误。)

您可以对帖子进行验证,如下所示

validates :posts_count, :numericality => { :greater_than_or_equal_to => 0 }
或者你可以这样做

before_save :set_posts_count

def set_posts_count
  posts_count = 0 if posts_count < 0
end
[posts_count, 0].max
保存前:设置发布次数
def set_posts_计数
如果posts\u count<0,则posts\u count=0
结束

出现问题的原因可能是,据我记忆所及,此方法不会初始化模型实例,因此它会发送一个直接的sql查询,如下所示:

UPDATE "Tags" SET "posts_counter" = COALESCE("posts_counter", 0) - 1 WHERE "Tags"."id" = 5

如果是这样,我不知道如何解决这个问题,可能您可以使用锁初始化模型实例,然后减少计数器,但是锁有它的缺点

您可以这样做

before_save :set_posts_count

def set_posts_count
  posts_count = 0 if posts_count < 0
end
[posts_count, 0].max

因此,如果
decrement\u count
想要使
posts\u count
-1,它将自动变为0,不会出现任何错误(顺便问一下,它不应该是
大于或等于=>0
?同意它应该大于或等于=>0,我不确定是否设置默认值,但你可以做的是进行方法调用,如果posts\u count出现验证错误,将默认值设置为0。这里是另一个选项。这很奇怪,我添加了第一个代码a我还用
-1
得到了
posts\u count
。Muhamamd Awais我甚至尝试了第二个代码:
self.posts\u count=0如果self.posts\u count<0
(我把它放在
tag.rb
)仍然得到了负数。