I have complicated models / forms. I don't want repeated records, so I want to merge records that have similar attributes. How would I cancel "save" using a before_save callback? This is what I'm thinking:
我有复杂的模型/表格。我不想重复记录,所以我想合并具有相似属性的记录。如何使用before_save回调取消“save”?这就是我所想的:
class ProductsColor < ActiveRecord::Base
before_save :check_for_similar_record
def check_for_similar_record
if ProductsColor.exist?(color_id: self.color_id, product_id: self.product_id)
# merge values with existing ProductsColor and stop self from saving
end
end
end
2 个解决方案
#1
24
To prevent record from being saved, you should simply return false
:
为了防止记录被保存,您应该返回false:
def check_for_similar_record
if ProductsColor.exists?(color_id: self.color_id, product_id: self.product_id)
# merge values
false
else
true
end
end
#2
45
Rails 5
As of Rails 5, you can signal that an operation should be aborted by explicitly calling throw :abort
inside your callback. The documentation section on cancelling callbacks (now) states:
从Rails 5开始,您可以通过显式地调用throw:abort在回调中来通知操作应该中止。关于取消回调(现在)的文件部分指出:
If a
before_*
callbackthrows :abort
, all the later callbacks and the associated action are cancelled.如果一个before_*回调抛出:abort,所有稍后的回调和相关操作将被取消。
The following section on transactions continues:
下一节继续讨论交易:
If a
before_*
callback cancels the action aROLLBACK
is issued. You can also trigger aROLLBACK
raising an exception in any of the callbacks, includingafter_*
hooks.如果before_*回调取消了操作,则发出回滚。您还可以在任何回调中触发回滚引发异常,包括after_*钩子。
Rails 4
The story is pretty similar to with Rails 5, except that callbacks should instead return false
. The corresponding parts of the documentation helpfully states
这个故事与Rails 5非常相似,只是回调应该返回false。文档的相应部分提供了有用的说明
If a
before_*
callback returns false, all the later callbacks and the associated action are cancelled. If an after_* callback returns false, all the later callbacks are cancelled.如果before_*回调返回false,则将取消以后的所有回调和相关操作。如果一个after_*回调返回false,则取消以后的所有回调。
Followed by
紧随其后的是
If a before_* callback cancels the action a
ROLLBACK
is issued. You can also trigger a ROLLBACK raising an exception in any of the callbacks, including after_* hooks.如果before_*回调取消了操作,则发出回滚。您还可以在任何回调中触发回滚引发异常,包括after_*钩子。
#1
24
To prevent record from being saved, you should simply return false
:
为了防止记录被保存,您应该返回false:
def check_for_similar_record
if ProductsColor.exists?(color_id: self.color_id, product_id: self.product_id)
# merge values
false
else
true
end
end
#2
45
Rails 5
As of Rails 5, you can signal that an operation should be aborted by explicitly calling throw :abort
inside your callback. The documentation section on cancelling callbacks (now) states:
从Rails 5开始,您可以通过显式地调用throw:abort在回调中来通知操作应该中止。关于取消回调(现在)的文件部分指出:
If a
before_*
callbackthrows :abort
, all the later callbacks and the associated action are cancelled.如果一个before_*回调抛出:abort,所有稍后的回调和相关操作将被取消。
The following section on transactions continues:
下一节继续讨论交易:
If a
before_*
callback cancels the action aROLLBACK
is issued. You can also trigger aROLLBACK
raising an exception in any of the callbacks, includingafter_*
hooks.如果before_*回调取消了操作,则发出回滚。您还可以在任何回调中触发回滚引发异常,包括after_*钩子。
Rails 4
The story is pretty similar to with Rails 5, except that callbacks should instead return false
. The corresponding parts of the documentation helpfully states
这个故事与Rails 5非常相似,只是回调应该返回false。文档的相应部分提供了有用的说明
If a
before_*
callback returns false, all the later callbacks and the associated action are cancelled. If an after_* callback returns false, all the later callbacks are cancelled.如果before_*回调返回false,则将取消以后的所有回调和相关操作。如果一个after_*回调返回false,则取消以后的所有回调。
Followed by
紧随其后的是
If a before_* callback cancels the action a
ROLLBACK
is issued. You can also trigger a ROLLBACK raising an exception in any of the callbacks, including after_* hooks.如果before_*回调取消了操作,则发出回滚。您还可以在任何回调中触发回滚引发异常,包括after_*钩子。