Rails:如何在我的模型中调用`self.save`并使其持久化到数据库中?

12
我试图让模型的逻辑保持在模型内部,但是我无法使其对自身进行修改并使其持久化到数据库中。
在我的控制器中:
@article.perform_some_calulcations!

在我的模型中:

def perform_some_calculations!
  self.foo.gsub!(/regexp/, 'string')
  self.save
end
如果我在方法中插入了debugger语句,并且在控制器中调用它后,@article.foo的值是正确的。但是,当我继续执行时,它不会保存到数据库中,而且webrick也不会报告任何UPDATE语句。出了什么问题?我不知道是否曾经需要做过这个,但肯定是有可能的吧?
3个回答

18

你的问题在于如果直接修改属性而不给它分配一个新值,Rails会认为没有新内容需要保存,因此会“优化”掉这个保存操作。

每个属性的写入访问器都会设置一个标志,因此save方法将知道它应该检查当前值是否真的与从数据库中读取的值不同。 这就是为什么self.foo = self.foo.gsub(/regexp/, 'string')可以起作用 (注意感叹号在这里不是必需的)

如果你需要原地修改属性,例如使用gsub!replace,请使用:

def perform_some_calculations!
  foo_will_change!
  self.foo.gsub!(/regexp/, 'string')
  self.save
end

这是一个好的实践吗?即模型在计算完某些内容后调用自身的保存函数? - Nicolas
这可能是主观的,但我认为当必要时,对象保存自身并没有什么错。然而,过度使用这种模式可能会影响性能。 - Arsen7

2
你的属性可能被保护了。请检查日志。如果是这种情况,那么:
self.save! 

或者
self.save(false)

尝试将您的定义中的感叹号去掉。


self.foo = self.foo.gsub!(/regexp/, 'string')

好主意,但是 self.save!self.save(false) 都有相同的结果。在任何地方都没有 attr_protected 的迹象,也没有在 webrick 日志中发出任何警告。 - nfm
无法从方法名称中删除 ! - nfm
哈哈,我刚刚独立发现了这个:P 如果使用gsub!,为什么还需要显式赋值呢? - nfm
我明白你的意思,因为你是在原地进行操作,但显然在这种情况下它不起作用。 - thenengah

0

我试图在一个类中创建一个方法,根据参数修改自身。使用 .save.save! 对我没有用,但如果我使用

self.update!({<PROP_NAME>: <NEW_VALUE>})

我看到了在我的数据库中持久化的更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接