use*_*684 9 controller transactions ruby-on-rails-3
我在Controller中有一个示例Action.
def some_action
product = Product.new
product.name = "namepro"
if product.save
client.update_attribute(:product_id,product.id)
end
end
Run Code Online (Sandbox Code Playgroud)
如何为此代码添加事务?我尝试使用此示例代码:
def some_action
**transaction do**
product = Product.new
product.name = "namepro"
if product.save
client.update_attribute(:product_create,Time.now)
end
**end**
end
Run Code Online (Sandbox Code Playgroud)
但它产生了这个错误:
undefined method `transaction'
Run Code Online (Sandbox Code Playgroud)
我读到在控制器中使用事务是一种不好的做法,但我不知道原因是什么(http://markdaggett.com/blog/2011/12/01/transactions-in-rails/)
在该示例中,如果已创建并保存产品并且客户端更新失败... Rails必须不执行任何操作.
谢谢.
Jim*_*art 25
如果您真的想要,可以在控制器中使用事务.正如你所说,这是不好的做法,但如果你想这样做,只需打电话Product.transaction do而不是transaction do. transaction是一个类方法ActiveRecord::Base,所以你需要在一个ActiveRecord派生类上调用它.您的应用程序中的任何模型类都可以执行此操作(如果您要为不同的模型连接到不同的数据库,那可能不是真的......但您可能不会这样做).
这是一个不好的做法的原因是它没有根据MVC范例正确地分离关注点.您的控制器不应该如此关注您的数据持久性实现.更好的方法是添加方法Product.也许是这样的:
def save_and_update_create_time
transaction do
if save
client.update_attribute(:product_create, Time.now)
end
end
end
Run Code Online (Sandbox Code Playgroud)
然后拨打电话product.save,而不是在控制器中呼叫product.save_and_update_client_create_time.您可能也需要传递client给该方法; 你的代码client来自哪里不清楚.如果它是一个属性product,那么上面的方法应该有效.
还有更好的,更多的Railsy方法,特别是如果一个人product知道它client而不需要任何控制器数据.然后你可以使用一个after_save回调,像这样(添加到Product类):
after_save :update_client
private
def update_client(product)
product.client.update_attribute(:product_create, Time.now)
end
Run Code Online (Sandbox Code Playgroud)
然后,每次Product保存时,将更新关联客户端上的字段.您可能必须引入一些代码来检查client第一个的存在.
除了更清晰的代码之外,使用回调的好处是整个回调链与保存一起在单个事务中运行; 您不需要手动创建事务.您可以在Rails文档中阅读有关回调的更多信息.
| 归档时间: |
|
| 查看次数: |
9095 次 |
| 最近记录: |