ActiveRecord验证失败后如何将数据保存到数据库?

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_somethingsomething方法MyModel

  • 调用MyModelLog.log_somethingafter_validation回调MyModel

在这两种情况下,验证失败时都会回滚创建,因为它位于验证事务中.当然,我也想在验证失败时记录.我真的不想登录文件或数据库之外的其他地方,因为我需要日志条目与其他模型的关系以及执行请求的能力.

我有什么选择?

Swa*_*and 8

嵌套事务似乎在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)

也许我已经简化了它,或者错过了一些观点.


Rob*_*rco 0

您可以使用嵌套事务。这样,回调中的代码将在与失败验证不同的事务中执行。ActiveRecord::Transactions::ClassMethods的 Rails 文档讨论了如何完成此操作。

  • 我可能不明白你的观点,但如果我为 log_something 执行嵌套事务,那么当“父”事务回滚时,子事务也会回滚 (2认同)