каков порядок операций ruby-on-rails при построении из хеша? - PullRequest
2 голосов
/ 08 июля 2010

У меня есть модель Attendance, которая позволяет пользователю вводить время начала, окончания и перерыва, каждый в виде объекта Time в рубине.Каждое посещение также имеет day (объект ruby ​​Date).Я хочу, чтобы элементы Date были одинаковыми, поэтому я переопределяю операторы присваивания следующим образом:

def startTime= (t)
  self[:startTime] = Time.mktime(day.year, day.month, day.day, t.hour, t.min)
end
def endTime= (t)
  self[:endTime] = Time.mktime(day.year, day.month, day.day, t.hour, t.min)
end
def breakTime= (t)
  self[:breakTime] = Time.mktime(day.year, day.month, day.day, t.hour, t.min)
end

Моя проблема заключается в том, что мои тесты не проходят только при переопределениифункция breakTime=.Все они терпят неудачу при вызовах к new, то есть att = Attendance.new @valid_attributes, в частности к breakTime=:

неопределенный метод `year 'для nil: NilClass

ОчевидноbreakTime= вызывается до того, как day определено на объекте, хотя startTime= и endTime= не вызывают так рано.Я понимаю, что это переопределение, вероятно, не элегантно, но я довольно плохо знаком с рельсами, поэтому я думаю, что кто-то уже совершал эту ошибку раньше.Как я должен делать это по-другому?

Ответы [ 3 ]

4 голосов
/ 08 июля 2010

Вместо переопределения установщиков атрибутов, используйте обратный вызов before_save, чтобы изменить атрибуты непосредственно перед сохранением модели:

class Attendance < ActiveRecord::Base
  before_save :update_timestamps

  protected
  def update_timestamps
    self.start_time = Time.mktime(day.year, day.month, day.day, start_time.hour, start_time.min)
    # And similarly for the other columns
  end
end

Для обзора работы обратных вызовов посмотрите на Руководство по валидации и обратным вызовам активной записи на сайте guides.rubyonrails.org.

1 голос
/ 08 июля 2010

Если вы хотите придерживаться подхода переопределения (который имеет преимущество в том, что даже несохраненные модели также соответствуют общим атрибутам, отформатированным во времени), вам нужно вызвать реализацию суперкласса в каждом из ваших:

def startTime= (t)
  t = Time.mktime(day.year, day.month, day.day, t.hour, t.min)
  super t
end
def endTime= (t)
  t = Time.mktime(day.year, day.month, day.day, t.hour, t.min)
  super t
end
def breakTime= (t)
  t = Time.mktime(day.year, day.month, day.day, t.hour, t.min)
  super t
end
1 голос
/ 08 июля 2010

Почему бы вам не использовать активные записи обратных вызовов. before_save может помочь вам здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...