mar*_*cgg 5 ruby validation activerecord ruby-on-rails
基本上我想要做的是在MyModelLog表中的MyModel上记录一个动作.这是一些伪代码:
class MyModel < ActiveRecord::Base
validate :something
def something
# test
errors.add(:data, "bug!!")
end
end
Run Code Online (Sandbox Code Playgroud)
我也有一个看起来像这样的模型:
class MyModelLog < ActiveRecord::Base
def self.log_something
self.create(:log => "something happened")
end
end
Run Code Online (Sandbox Code Playgroud)
为了记录我试图:
添加MyModelLog.log_something的something方法MyModel
调用MyModelLog.log_something的after_validation回调MyModel
在这两种情况下,验证失败时都会回滚创建,因为它位于验证事务中.当然,我也想在验证失败时记录.我真的不想登录文件或数据库之外的其他地方,因为我需要日志条目与其他模型的关系以及执行请求的能力.
我有什么选择?
嵌套事务似乎在MySQL中起作用.
这是我在新生成的rails(使用MySQL)项目上尝试的内容:
./script/generate model Event title:string --skip-timestamps --skip-fixture
./script/generate model EventLog error_message:text --skip-fixture
class Event < ActiveRecord::Base
validates_presence_of :title
after_validation_on_create :log_errors
def log_errors
EventLog.log_error(self) if errors.on(:title).present?
end
end
class EventLog < ActiveRecord::Base
def self.log_error(event)
connection.execute('BEGIN') # If I do transaction do then it doesn't work.
create :error_message => event.errors.on(:title)
connection.execute('COMMIT')
end
end
# And then in script/console:
>> Event.new.save
=> false
>> EventLog.all
=> [#<EventLog id: 1, error_message: "can't be blank", created_at: "2010-10-22 13:17:41", updated_at: "2010-10-22 13:17:41">]
>> Event.all
=> []
Run Code Online (Sandbox Code Playgroud)
也许我已经简化了它,或者错过了一些观点.
您可以使用嵌套事务。这样,回调中的代码将在与失败验证不同的事务中执行。ActiveRecord::Transactions::ClassMethods的 Rails 文档讨论了如何完成此操作。
| 归档时间: |
|
| 查看次数: |
952 次 |
| 最近记录: |