2

假设我在 Rails 中想要这样的东西:

class Proposal < ActiveRecord::Base
    def interest_level
        self.yes_votes.count - self.no_votes.count
    end

  private
    def yes_votes
        self.votes.where(:vote => true)
    end

    def no_votes
        self.votes.where(:vote => false)
    end
end
  1. 我在上面的代码中基本上做错了什么?(我意识到这可能在很多方面都很糟糕。)
  2. 从 Rails 的角度来看,这样做的正确方法是什么?
  3. 从数据库的角度来看,我应该注意哪些注意事项?(例如,即使像上面这样的代码可能的,我猜它在数据库方面会过分。但我自然不太确定。)
4

3 回答 3

2

类提案 < ActiveRecord::Base

def interest_level
    self.votes.sum('votes', :conditions => {:votes = true}) - self.votes.sum('votes', :conditions => {:votes = false})
end

结尾

谢谢,阿努博

于 2010-09-23T08:01:09.327 回答
2

考虑到数据库加载,我建议实现自定义计数器缓存。我会这样做:

class Vote < ActiveRecord::Base

    def after_create
      self.update_counter_cache
    end

    def after_destroy
      self.update_counter_cache
    end

    def update_counter_cache
      self.proposal.yes_votes_count = self.proposal.votes.where(:vote=>true)
      self.proposal.no_votes_count = self.proposal.votes.where(:vote=>false)
      self.propsal.save
    end
end

请注意,您必须在Proposal模型中添加两​​列。

add_columns_migration.rb

add_column :proposals, :yes_votes_count, :integer
add_column :proposals, :no_votes_count, :integer
于 2010-09-23T11:52:35.733 回答
1

我真的没有看到您的代码有任何明显错误。尽管有很多方法可以完成您似乎正在尝试做的事情,但您的方法似乎应该可以正常工作(尽管我对 Arel 的经验有限)。

另一种解决方法可能是简单地更改interest_level方法:

def interest_level
    self.votes.count - self.no_votes.count * 2  # same as (total - no_votes) - no_votes
end

上面可能会稍微快一些,尽管我非常怀疑它会产生很大的不同,计数查询在索引列上非常快,并且您的该方法版本更易于阅读

于 2010-09-23T08:48:03.860 回答