2011-12-28 64 views
52

我有一个具有:credits特性的用户模型。我想要一个简单的按钮,将增加5到用户的学分,通过所谓的路线“添加”,这样/用户/ 3 /加将增加5到用户ID的学分= 3Rails:无需调用回调即可更新模型属性

def add 
    @user = User.find(params[:id]) 
    @user.credits += 5 
    redirect_to root_path 
end 

也就是说我的控制器的相关部分。问题是,我不想调用@ user.save,因为我有一个before_save回调,它根据当前UTC时间重新加密用户的密码。我只想简单地将5添加到属性并避免回调,我从来没有想过这么简单的事情可能会很难。

编辑:

我改变了回调:before_create, 这里是我的新控制器代码(相关部分):

def add 
    @user = User.find(params[:id]) 
    @user.add_credits(5) 
    @user.save 
    flash[:success] = "Credits added!" 
    redirect_to root_path 
    end 

,这里是我的模型代码:

def add_credits(num) 
    self.credits = num 
end 

编辑2:

好吧,这是一个验证问题这使“EDIT”中的更改无法正常工作,但我仍然喜欢无需回调即可更新原始问题的答案!

+0

我提供了一个不触发回调的方法列表,Finbarr和我都建议使用条件回调 - 您在寻找哪些其他解决方案? – 2011-12-28 04:21:27

回答

1

也许你的其他before_save钩子应该在再次加密之前检查用户的密码是否已经改变了。

1

您有多种选择,包括更改您使用的回拨,例如after_create

您可以在不触发回调的情况下更新列,请参阅AR指南中的Skipping Callbacks。例如,update_column不会触发回调。上一个链接列出了非触发功能。

您也可以使用任何Conditional Callback表单(甚至观察员)来更改密码。参见ActiveModel::Dirty,例如@user.password_changed?

+0

好的,我把它改成了“after_create”,但它仍然不行!查看我编辑的新代码,我无法获得学分更改。 – 2011-12-28 01:56:17

+0

@hatboysam好吧,它做了一些不同的事情 - 在你添加之前,现在你正在设置。使用'save!'查看是否有异常(和/或检查日志,和/或删除回溯消音器)。 – 2011-12-28 02:02:38

2

您应该能够使用update_all来避免触发回调。

def add 
@user = User.find(params[:id]) 
User.where(:id=>@user.id).update_all(:credits => @user.credits+5) 
redirect_to root_path 
end 

我宁愿把这个逻辑放在模型中,但这应该可以解决你原来的问题,如控制器中的spec'd。

2

我想你应该在这种情况下使用方法update_counters。使用它像这样在你的控制器动作:

def add 
    User.update_counters params[:id], :credits => 5 
    redirect_to root_path 
end 
+0

update_counters/increment_counter也可以使用2.x很好! – rogerdpack 2013-01-30 19:06:59

5

要更新不进行回调多个属性你可以在你的模型中使用update_all:

self.class.update_all({name: value, name: value}, self.class.primary_key => id) 

如果你真的我希望你甚至可以尝试一下update_columns方法,并将它混入你的活动记录基类中。

要更新一个属性,您可以使用update_column。此外,还有可在轨道发现了一些具体的方法指导http://guides.rubyonrails.org/active_record_callbacks.html#skipping-callbacks

+1

终于可以与rails 2.x一起使用了,谢谢! – rogerdpack 2013-01-27 05:05:18

2

对于mongoid有几个选项,我结束了使用http://mongoid.org/en/mongoid/docs/persistence.html 具体来说,可以使用:

person.set(name:"Robert Pulson") 

并且不会发出回调。非常酷。

+0

其person.set(:名称,“Robert Pulson”) – 2016-12-10 14:20:04

+1

@JudeCalimbas不,它的不是,ArgumentError:错误的参数数量(给出2,预期1) – rept 2017-08-31 23:40:52

1

作为一般的答案,在轨道4,这是一个简单的方法,而不会触发回调更新属性:

@user.update_column credits:5 

如果您需要在不触发回调来更新多个属性:

@user.update_columns credits: 5, bankrupt: false 

有其他选项here in the Rails Guides如果你愿意,但我发现这种方式是最简单的。

+1

user.update_column信用:5 不起作用。它应该是 user.update_column'credits',5 – 2017-03-28 01:56:44

+0

我使用的是Rails 4.2,这对我来说确实有效。该行生成以下查询:“UPDATE”users“SET”credits“= $ 1,”updated_at“= $ 2 WHERE”users“。”id“= $ 3 [[”credits“,5],[”updated_at“,”2017 -04-01 21:34:52.746626“],[”id“,1]]' – Matt 2017-04-01 21:37:05