问题:我正在寻找一个在DB事务开始之前执行的ActiveRecord(Rails 3.2)回调钩子。
如果它不存在(我认为它不存在),那么我正在寻找任何关于猴子修补ActiveRecord的建议,以便我们自己实现这样的方法。
我尝试过什么
看过ActiveRecord文档并玩弄代码后,似乎只有'after_commit'才能保证在事务之外执行。其他所有内容(“before_validation”,“before_save”,“before_commit”)都在事务中运行。我试过覆盖'交易'方法:
VERSION BUILD=9030808 RECORDER=FX
SET !ERRORIGNORE YES
SET !DATASOURCE "C:/Users/Tester/Desktop/file_name.csv"
SET !DATASOURCE_COLUMNS 1
SET !TIMEOUT_STEP 30
SET !EXTRACTDIALOG NO
SET !LOOP 1
SET !DATASOURCE_LINE {{!LOOP}}
URL GOTO=https://openflights.org/html/apsearch
SET !EXTRACT NULL
TAG POS=1 TYPE=INPUT:CHECKBOX FORM=NAME:searchform ATTR=NAME:iatafilter CONTENT=NO
TAG POS=1 TYPE=INPUT:TEXT FORM=NAME:searchform ATTR=NAME:iata CONTENT={{!COL1}}
TAG POS=1 TYPE=INPUT:BUTTON FORM=NAME:searchform ATTR=*
TAG POS=6 TYPE=INPUT:BUTTON ATTR=*
WAIT SECONDS=1
TAG POS=1 TYPE=INPUT:TEXT FORM=NAME:searchform ATTR=NAME:iata EXTRACT=TXT
TAG POS=1 TYPE=INPUT:TEXT FORM=NAME:searchform ATTR=NAME:y EXTRACT=TXT
TAG POS=1 TYPE=INPUT:TEXT FORM=NAME:searchform ATTR=NAME:x EXTRACT=TXT
SAVEAS TYPE=EXTRACT FOLDER="C:\\Users\\Tester\\Desktop" FILE=coordinates.csv
但这很复杂,因为事务是一个类方法,并且必须在每个模型实例中注册回调。最重要的是,它不能保证在数据库事务之外运行,因为它可以嵌套:
class User < ActiveRecord::Base
included do |base|
base.instance_eval do
def before_transaction
### DO STUFF
end
def transaction(options = {}, &block)
before_transaction { super(options, &block) }
end
end
end
根据ActiveRecord的实现方式,不确定我想要什么是可能的,因为可能无法知道另一个事务是否已经开始并随后调用回调。无论如何,我认为这里值得一提。
背景
我正在尝试将现有的Rails模型(让我们称之为用户)'同步'到位于elswhere的用户服务。用户服务应该充当真相的来源。
每当Rails用户模型发生更新时,我想在保存到DB(只有Rails项目使用)之前验证+首先将更改提交给用户服务。然后,Rails项目的DB用作直写缓存(为什么数据库用于缓存?遗留代码的原因)。
如果我们可以在写入数据库之前调用服务,我们不必担心回滚事务(并处理回滚失败时会发生什么!)。但是,我对在开放数据库事务中调用服务犹豫不决,这就是为什么我要研究是否可以建立一个“before_transaction”回调。
答案 0 :(得分:0)
为什么不编写一个处理所有这些功能的服务对象?
class UserService
attr_accessor :user
def initialize(user, params)
@user = user
@params = params
end
def save
external_result = API.call_to_external
if external_result
@user.update(@params)
end
end
end
user_service = UserService.new(user, params)
user_service.save