Консолидация целых чисел в Ruby (на рельсах) - PullRequest
0 голосов
/ 10 февраля 2011

У меня есть класс, который содержит два целых числа (a и b) и ссылку на сущность.

Я хочу иметь возможность сообщать о сумме всех a и b в пределах класса.

Например, у меня может быть три записи:

Entity    1  2  3 
a         5  9  3 
b         8  1  2

Я хочу, чтобы мой консолидированный результат для a был 17, а для b 11.

Меня интересует представлениена лучший подход к этому.Теперь я могу суммировать все на лету, но если есть много записей, которые могут быть медленными.

Или я мог бы поддерживать поддельную сущность, которая содержит консолидированный результат и обновляется каждый раз, когда любой из других объектовобновление.

Или у меня может быть другой класс для сводной даты?

Все мысли оценены.

Спасибо, Крис

Ответы [ 3 ]

1 голос
/ 10 февраля 2011

Самый простой способ - отслеживать эту информацию в классе. Например, предположим, что у нас есть несколько FruitBaskets, которые могут содержать любое количество apples и bananas. В любой момент мы хотим узнать общее количество яблок и бананов во всех корзинах.

module FruitCounter
  attr_accessor :apples, :bananas

  def apples; @apples ||= 0; end
  def bananas; @bananas ||= 0; end
end

class FruitBasket
  class << self
    include FruitCounter   # Keeps track of the total for all FruitBaskets.
  end

  include FruitCounter

  def apples=(v)
    d = v - self.apples       # Note the difference.
    @apples = v               # Set the new value for this instance.
    self.class.apples += d    # Adjust the total by the difference.
  end

  def bananas=(v)
    d = v - self.bananas
    @bananas = v
    self.class.bananas += d
  end
end

Давайте посмотрим на это в действии:

first = FruitBasket.new
 => #<FruitBasket:0x97be6f8> 
first.apples = 10; first.bananas = 15

FruitBasket.apples
 => 10 
FruitBasket.bananas
 => 15

Пока все хорошо. Как насчет другой корзины?

second = FruitBasket.new
 => #<FruitBasket:0x97b28e4> 
second.apples = 30; second.bananas = 20

FruitBasket.apples
 => 40 
FruitBasket.apples == first.apples + second.apples
 => true 

А теперь давайте изменим содержимое первой корзины:

first.apples = 3
 => 3 
FruitBasket.apples
 => 33
FruitBasket.apples == first.apples + second.apples
 => true 

Вот, пожалуйста!

1 голос
/ 10 февраля 2011

Я думаю, вам нужен метод класса, что-то вроде:

def self.consolidated_a
  if @@cache_invalid
    @@cached_a = all.collect(0) { |sum, x| sum + x.a }
  end
  @@cached_a
end

Если вы хотите, чтобы он кэшировался, вы можете, например, иметь переменную класса с именем @@cache_invalid и устанавливать ее в значение true в любое время a или b. Затем вы можете проверить это и вернуть кэшированное значение, если false, и запустить приведенный выше код, если true (сейчас я отредактировал код для включения этого изменения).

0 голосов
/ 10 февраля 2011

Я вижу два способа, которыми вы можете выбрать:

  1. вычислить сумму a и b с нетерпением, всегда, когда любое из этих изменений
  2. вычисляется лениво, толькокогда кому-то нужно консолидированное значение

Вы должны знать, какая из вышеперечисленных моделей больше соответствует вашим потребностям.Я бы назвал этот путь следующим образом:

class ABCounter

  @consolidated_apples = 0
  @consolidated_pears = 0

  class << self
    attr_accessor :consolidated_apples, :consolidated_pears
  end

  attr_accessor :apples, :pears
  def initialize
    @apples = 0
    @pears = 0
  end

  def apples=(x)
    ABCounter.consolidated_apples += x - @apples
    @apples = x
  end

  def pears=(x)
    ABCounter.consolidated_pears += x - @pears
    @pears = x
  end
end

Ленивый путь должен пройти через все созданные экземпляры ABCounter и суммировать значения a и b.

...