如何获得许多子列?

时间:2015-03-13 05:31:52

标签: ruby-on-rails activerecord

我有两个表,MemberMemberRecord

这是他们的关系:

# Member Model
class Member < ActiveRecord::Base
  has_many :member_records, :dependent => :destroy
end
# MemberRecord Model
class MemberRecord < ActiveRecord::Base
  belongs_to :member
end

MemberRecord中有很多列:two_pointer_attempt, two_pointer_made, three_pointer_attempt, three_pointer_made, free_throws_attempt, free_throws_made, offensive_rebound, defensive_rebound, assist, block, steal, turnover, foul, score

我可以更有效地获得这些列的总和吗?

这是我到目前为止所做的:

class Member < ActiveRecord::Base
  belongs_to :team
  has_many :member_records, :dependent => :destroy

  validates :name, :number, presence: true
  validates_uniqueness_of :name, scope: :team_id
  validates_inclusion_of  :number, in: 0..99

  def sum_two_pointer_made
    self.member_records.sum(:two_pointer_made)
  end

  def sum_two_pointer_attempt
    self.member_records.sum(:two_pointer_attempt)
  end

  def sum_two_pointer_total
    sum_two_pointer_made + sum_two_pointer_attempt
  end

  def sum_three_pointer_made
    self.member_records.sum(:three_pointer_made)
  end

  def sum_three_pointer_attempt
    self.member_records.sum(:three_pointer_attempt)
  end

  def sum_three_pointer_total
    sum_three_pointer_made + sum_three_pointer_attempt
  end

  def sum_free_throws_made
    self.member_records.sum(:free_throws_made)
  end

  def sum_free_throws_attempt
    self.member_records.sum(:free_throws_attempt)
  end

  def sum_free_throws_total
    sum_free_throws_made + sum_free_throws_attempt
  end

  def sum_offensive_rebound
    self.member_records.sum(:offensive_rebound)
  end

  def sum_defensive_rebound
    self.member_records.sum(:defensive_rebound)
  end

  def sum_assist
    self.member_records.sum(:assist)
  end

  def sum_block
    self.member_records.sum(:block)
  end

  def sum_steal
    self.member_records.sum(:steal)
  end

  def sum_turnover
    self.member_records.sum(:turnover)
  end

  def sum_foul
    self.member_records.sum(:foul)
  end

  def sum_score
    self.member_records.sum(:score)
  end

end

1 个答案:

答案 0 :(得分:1)

我将为您举例说明两列,您可以根据列数扩展它。

class Member < ActiveRecord::Base
  # add associations here as already present

  MR_SUM_COLUMNS = %w{
    assist
    block
  } # add more member record columns here

  MR_SUM_COLUMNS.each do |column|
    define_method "member_record_#{column}_sum" do
      member_record_sums.send(column)
    end
  end

  private

  def member_record_sums
    @_member_record_sums ||=
      begin
        tn = MemberRecord.table_name

        sums_str =
          MR_SUM_COLUMNS.map do |c|
            "SUM(#{tn}.#{c}) AS #{c}"    
          end.join(', ')

        self.member_records.select(sums_str).first
      end
  end
end

m = Member.first
s1 = m.member_record_assist_sum
s2 = m.member_record_block_sum

说明:

ActiveRecord&#39; select方法中,您可以将列的总和存储为特定值。例如:

# you have only two members with ids 1 and 2
m = Member.select("SUM(id) AS id_sum").first
m.id_sum #=> 3

因此,我们在member_records方法中一次性存储member_record_sums的所有总和。我们还使用实例变量来存储结果,以便后续对方法的调用不会查询数据库。

从那里,我们所要做的就是动态定义求和方法。