在保存之前,如何在ActiveRecord对象中设置属性?

时间:2010-09-16 09:39:28

标签: ruby-on-rails activerecord

我正在尝试理解Active Record Callbacks,但它们不起作用,就像我想要的那样。

e.g。

模型

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 个答案:

答案 0 :(得分:8)

回调问题是如果falseitem1为假,则会返回item2

来自Active Record Callbacks文档:

  

如果before_validation回调的返回值可以评估为false,则流程将中止,Base#save将返回false

解决方案很简单;在回调结束时返回true,如下所示:

def check_done
  self.done = (item1 && item2)
  return true
end

答案 1 :(得分:3)

before_save { |record|
  record.done = item1 && item2
}

答案 2 :(得分:0)

请尝试:

def check_done
  if item1 && item2
    done = true
  else
    done = false
  end
end

答案 3 :(得分:0)

在私人表单中,尝试

def check_done
  self.done = (self.item1 && self.item2) ? true : false
end