2009-04-16 3 views
0

У меня есть модель, которая генерируется путем анализа файла данных. Есть несколько интересных значений, которые отсутствуют в исходном файле данных, но могут быть получены из тех, которые есть.Ленивая настройка атрибутов модели в Rails?

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

Я попытался это:

def profit 
    if not self[:profit] 
    update_attribute :profit, expensive_computation 
    end 
    self[:profit] 
end 

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

UPDATE:

Оказывается, проблема была не в методе, а в find_by_sql заявлением ранее на том, что у Rails запутался о идентификаторах моделей. Код, который я получил, был следующим:

def profit 
    unless read_attribute(:profit) 
    update_attribute(:profit, expensive_computation) 
    self.save! 
    end 
    read_attribute(:profit) 
end 

ответ

2

Вы создаете новый метод и извлекаете из него логику чтения. Может быть что-то вроде этого

def update_profit 
    update_attribute :profit, expensive_computation 
end 

Таким образом, вы можете отделить логику чтения и просто использовать метод, чтобы получить profit, что рельсы дает вам.

@model.profit 

Где @model является экземпляром независимо от класса атрибут profit в.

0

Если код должен идти будет зависеть от того, когда это возможно, чтобы рассчитать прибыль (например, как только запись сначала будет сохранено, или это будет иногда позже?), и может ли прибыль когда-либо измениться.

В целом, вероятно, будет лучше поставить расчет в какой-то before_create/before_save вызова, который сохраняет его только тогда, когда это можно рассчитать и/или изменил

vrish88 это правильно, что вы, вероятно, следует оставить profit, если вам действительно не нужно вычислять это на лету, поскольку данные необходимы. Если это действительно то, что вам нужно, попробуйте:

def profit 
    update_attribute(:profit, expensive_computation) unless read_attribute(:profit) 

    read_attribute(:profit) 
end 
0

Это отлично работает для меня. Моя первая мысль: у вас есть опечатка в линии if not self[:profit]?

0
def profit 
    super || update_attribute(:profit, expensive_computation) 
    return super 
end 

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

В противном случае (т.е. profit столбца имеет значение nil) использовать метод update_attribute для вычисления значения profit и хранить его в базу данных, а затем просто возвращает значение из базы данных снова.

Если вы предпочли бы получить значение profit, если он уже находится в базе данных или просто true если дорогой расчет закончилась, просто сделать это (update_attribute возвращает истину или ложь):

def profit 
    super || update_attribute(:profit, expensive_computation) 
end