Как установить атрибуты в объекте ActiveRecord перед его сохранением? - PullRequest
5 голосов
/ 16 сентября 2010

Я пытаюсь понять обратные вызовы Active Record, но они не работают, как я хочу.

например,

Модель

Checklist<ActiveRecord...
attr_accessible :item1, :item2, :done # they are all boolean

before_save :check_done

private
def check_done
  if item1 && item2
   write_attribute :done, true
  else
   write_attribute :done, false
  end
end

, это не сработает, если я создаю экземпляр объекта в консоли и пытаюсь сохранить его, операция сохранения возвращает "false":(

Что не так с этим кодом? Заранее спасибо:)

РЕДАКТИРОВАТЬ: Похоже, что-то не так с вызовом before_save, если я использую "after_save ", код работает ... но атрибут не сохраняется (очевидно).Это действительно странно

РЕДАКТИРОВАТЬ 2 Wierd ... Журналы разработки показывают это

FROM sqlite_master
 WHERE type = 'table' AND NOT name = 'sqlite_sequence'
[0m
  [1m[35mChecklist Load (0.2ms)[0m  SELECT "checklists".* FROM "checklists" ORDER BY checklists.id DESC LIMIT 1
WARNING: Can't mass-assign protected attributes: id

, но это действительно странно, потому что если я удаляю строку attr_accessible, явсе равно получаю эту ошибку ...

РЕДАКТИРОВАТЬ 3 Если кто-нибудь спросит, да, я пытаюсь обновить существующую запись.

РЕДАКТИРОВАТЬ 4 Да, мне нравится редактировать Если я наберу в консоли

c.save => # false
c.errors => #<OrderedHash {}>

Ответы [ 4 ]

8 голосов
/ 17 сентября 2010

Проблема с вашим обратным вызовом в том, что он возвращает false, если либо item1, либо item2 имеет значение false.

Из обратных вызовов активной записи документация:

Если возвращаемое значение обратного вызова before_validation может быть оценено как false, процесс будет прерван и Base#save вернет false.

Решение простое; вернуть true в конце вашего обратного вызова, например:

def check_done
  self.done = (item1 && item2)
  return true
end
3 голосов
/ 17 сентября 2010
before_save { |record|
  record.done = item1 && item2
}
0 голосов
/ 16 сентября 2010

В вашем личном методе, попробуйте

def check_done
  self.done = (self.item1 && self.item2) ? true : false
end
0 голосов
/ 16 сентября 2010

Пожалуйста, попробуйте:

def check_done
  if item1 && item2
    done = true
  else
    done = false
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...