Ruby on Rails - 我可以在保存数据之前修改数据吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1187138/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ruby on Rails - Can I modify data before it is saved?
提问by SpleenTea
Quick example: A user enters a username into a form, and I need to make that text username before storing it in the app's database, thereby making it permanently lowercase.
快速示例:用户在表单中输入用户名,我需要在将该文本用户名存储在应用程序的数据库中之前制作该文本用户名,从而使其永久小写。
Where would I put this code, and how would I access the data to be lowercased?
我将把这段代码放在哪里,我将如何访问要小写的数据?
Thanks.
谢谢。
回答by Michael Siebert
you should overwrite the attribute writer:
您应该覆盖属性编写器:
class User < ActiveRecord::Base
def username=(val)
write_attribute(:username, val.downcase)
end
end
回答by effkay
You could use one of ActiveRecords callbacks in your User model, eg something like that:
您可以在用户模型中使用 ActiveRecords 回调之一,例如:
before_save { |user| user.username = user.username.downcase }
回答by James Boutcher
In your User model (models/user.rb), take advantage of ActiveRecord callbacks:
在您的用户模型 (models/user.rb) 中,利用 ActiveRecord 回调:
before_save do
self.username = self.username.downcase
end
回答by Alex Levine
I spent a while looking up a bug stopping me from utilizing this code. My database was rolling back every time I tried to intercept an attribute and change it to falsebefore saving.
我花了一段时间查找阻止我使用此代码的错误。每次我尝试拦截一个属性并将其更改为false保存之前,我的数据库都会回滚。
I'm contributing my answer here because this thread was the first Google result for accomplishing this task but didn't cover the whole returning falseproblem.
我在这里提供我的答案,因为该线程是完成此任务的第一个 Google 结果,但没有涵盖整个返回false问题。
If any of your callbacks return falseeverything will be rolled back in the db.
如果您的任何回调返回,则false所有内容都将在数据库中回滚。
I was trying to set an Offer to be created to not be accepted in the database or @offer.accepted = false. The problem was that this line caused the whole method to return false and rollback the entire process.
我试图将要创建的要约设置为不被数据库或@offer.accepted = false. 问题是这一行导致整个方法返回false并回滚整个过程。
I fixed it by tossing in an implicit return trueafterwards
我在一个隐含的回报固定它的折腾true之后
Code that worked:
有效的代码:
before_save {|offer| offer.accepted = false; true}
before_save {|offer| offer.accepted = false; true}
Takeaway: Your callbacks can't return falseif you want them to succeed.
要点:false如果您希望回调成功,您的回调将无法返回。
Source: rails 3 : Do i need to give return true in a before_save callback for an object.save to work?
来源:rails 3:我是否需要在 before_save 回调中返回 true 才能使 object.save 工作?
回答by suffering
def username=(str)
super(str.downcase)
end
I thought this much easier.
我认为这要容易得多。
回答by Gishu
In the general case, The submit button on the form should delegate to a controller action where params[:user_name] is available. You could lowercase that before doing a SomeModel.update(params) or create(params).
在一般情况下,表单上的提交按钮应委托给 params[:user_name] 可用的控制器操作。您可以在执行 SomeModel.update(params) 或 create(params) 之前将其小写。
So you could do it in the controller action.
所以你可以在控制器动作中做到这一点。
回答by Mike Trpcic
I would suggest adding an Observerto the model and doing this action in the before_save method. Then it is guaranteed to lowercase the username no matter which controller or action is creating it, and if there is an issue performing any action within the observer, an exception is thrown and the object won't save.
我建议在模型中添加一个观察者并在 before_save 方法中执行此操作。然后,无论是哪个控制器或动作创建它,它都保证小写用户名,并且如果在观察者中执行任何动作时出现问题,则会引发异常并且不会保存该对象。
Edit: Please note that you can'tdo a Model.save within the before_save tied to that model, otherwise you end up in an infinite loop. You'll need to do an update_attributes or something.
编辑:请注意,您不能在绑定到该模型的 before_save 中执行 Model.save,否则最终会陷入无限循环。您需要执行 update_attributes 或其他操作。

