我的模型中有一个before_save回调函数,它在将2个字段保存到数据库之前对其进行加密。
aggregate(V2 ~V1, rbind(df1, df2), FUN = sum)
# V1 V2
#1 Anna 30
#2 Charlie 30
#3 Julia 60
#4 Tom 80
情况与Devise models run before_save multiple times?非常相似。当我调用Model.create!(...) - 其中包含需要加密的2个字段时,before_save会被调用两次,最后会被加密两次。
class Account < ActiveRecord::Base
before_save :encrypt_credentials, if: "!username.blank? && !password.blank?"
def encrypt_credentials
crypt = ActiveSupport::MessageEncryptor.new(ENV['KEY'])
self.username = crypt.encrypt_and_sign(username)
self.password = crypt.encrypt_and_sign(password)
end
def decrypted_username
crypt = ActiveSupport::MessageEncryptor.new(ENV['KEY'])
crypt.decrypt_and_verify(username)
end
def decrypted_password
crypt = ActiveSupport::MessageEncryptor.new(ENV['KEY'])
crypt.decrypt_and_verify(password)
end
end
为什么before_save被多次调用?我不喜欢上面链接的帖子的解决方案,我不想做新的/ build然后保存。
答案 0 :(得分:1)
这是用户错误:(在调用account = Account.create!之后,我有其他代码,名为save!返回模型:account.foo = bar; account.save!。这显然再次称为befor_save并重新加密我的字段。我最终得到了这样的东西:
GET https://{instance}/DefaultCollection/{project}/{team}/_apis/work/TeamSettings/Iterations/{iterationid}/Capacities?api-version={version}
GET https://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/Fabrikam-Fiber/_apis/work/teamsettings/iterations/2ec76bfe-ba74-4060-970d-4567a3e997ee/capacities?api-version=2.0-preview.1
{
"values": [
{
"teamMember": {
"id": "8c8c7d32-6b1b-47f4-b2e9-30b477b5ab3d",
"displayName": "Chuck Reinhart",
"uniqueName": "fabrikamfiber3@hotmail.com",
"url": "https://fabrikam-fiber-inc.vssps.visualstudio.com/_apis/Identities/8c8c7d32-6b1b-47f4-b2e9-30b477b5ab3d",
"imageUrl": "https://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/_api/_common/identityImage?id=8c8c7d32-6b1b-47f4-b2e9-30b477b5ab3d"
},
"activities": [
{
"capacityPerDay": 0,
"name": null
}
],
"daysOff": [],
"url": "https://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/6d823a47-2d51-4f31-acff-74927f88ee1e/748b18b6-4b3c-425a-bcae-ff9b3e703012/_apis/work/teamsettings/iterations/2ec76bfe-ba74-4060-970d-4567a3e997ee/capacities/8c8c7d32-6b1b-47f4-b2e9-30b477b5ab3d"
}
]
}
答案 1 :(得分:0)
选项1(使用回调可能会出错):
简短答案:使用after_save代替before_save
长答案:How to organize complex callbacks in Rails?
使用时:
account = Account.new
account.save
您每次都触发before_save钩子。
选项2(可能是错误):
也许您实际上是在多次触摸唱片。
例如:
def create
@account = Customer.find(params[:customer_id]).accounts.create(account_params)
if @account.save
redirect_to customer_account_path(@account.customer.id, @account.id)
else
render :new
end
end
实际上,您正在通过创建和保存来触摸它。在这种情况下,我建议:
def create
@account = Customer.find(params[:customer_id]).accounts.build(account_params)
if @account.save
redirect_to customer_account_path(@account.customer.id, @account.id)
else
render :new
end
end
Build不会尝试保存记录,因此您不会再遇到任何问题。希望这可以帮助!祝你有美好的一天!