ActiveRecord的方法递减!更新其他属性也是如此。这是为什么? [英] ActiveRecord method decrement! updates other attributes as well. Why is that?

查看:95
本文介绍了ActiveRecord的方法递减!更新其他属性也是如此。这是为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基本的身份验证系统宛若迈克尔·哈特尔的的 Ruby on Rails的教程的。基本上,一个记令牌存储在cookie中。我实现了瑞安贝特的β-邀请从Railscast#124,在那里你可以发送数量有限的邀请。虽然这样做,我跑进了the发送邀请后,当前用户得到了注销。这是由该code的邀请模式造成的:

invitation.rb

  belongs_to的:发件人:=将class_name> '用户'
[...]
before_create:decrement_sender_count,:如果=> :发件人
[...]
高清decrement_sender_count
  sender.decrement! :invitation_limit
结束
 

在日志中我看到sender.decrement!不仅更新了invitation_limit但reme​​mber_token还有:

 更新用户SETinvitation_limit= 9982,remember_token='PYEWo_om0iaMjwltU4iRBg'的updated_at='2012-07-06 09:57:43.354922WHERE用户。ID= 1
 

我发现了一个丑陋的解决方法,但我很想知道这个问题确实是。因为我不知道从哪里开始,我会告诉你从用户控制器的更新方法。还有什么可能是相关的?

users_controller.rb

 高清更新
  @user = User.find(PARAMS [:ID])
  如果@ user.update_attributes(PARAMS [:用户])
    闪光[:成功= T('success.profile_save)
    sign_in @user
    redirect_to时@user
  其他
    flash.now [:错误] = T('error.profile_save)
    渲染编辑
  结束
结束
 

<=h2_linDIV class>的解决方案

调用其中的

递减!保存课程火灾保存回调。它看起来像这本书指导您这样做

  before_save:create_remember_token
高清create_remember_token
  self.remember_token = SecureRandom.urlsafe_base64
结束
 

这意味着节约了用户始终无效记得令牌。我想这是这样,当用户更改其密码记住令牌变化太大,但它意味着有一些明显的附带损害。

您可以使用 decrement_counter 这在本质上确实

 更新用户设置counter_name = counter_name  -  1其中id = 12345
 

不运行任何回调。这也避免了一些竞争条件的方案。然而改变,每当用户改变必将改变有时令牌时,你不要指望它的令牌 - 你可能只想相关的(也许当凭据发生了变化)

当更改

I have a basic authentication system just like in Michael Hartl's Ruby on Rails Tutorial. Basically, a remember token is stored in a cookie. I implemented Ryan Bate's Beta-Invitations from Railscast #124, where you can send a limited number of invitations. While doing that, I ran into the problem that the current user got logged out after sending an invitation. This was caused by this code in the invitation model:

invitation.rb

belongs_to :sender, :class_name => 'User'
[...]
before_create :decrement_sender_count, :if => :sender
[...]
def decrement_sender_count
  sender.decrement! :invitation_limit
end

In the logs I saw that sender.decrement! not only updated the invitation_limit but the remember_token as well:

UPDATE "users" SET "invitation_limit" = 9982, "remember_token" = 'PYEWo_om0iaMjwltU4iRBg', "updated_at" = '2012-07-06 09:57:43.354922' WHERE "users"."id" = 1

I found an ugly workaround but I would love to know what the problem really is. Since I don't know where to start, I'll show you the update method from the users controller. What else could be relevant?

users_controller.rb

def update
  @user = User.find(params[:id])
  if @user.update_attributes(params[:user])
    flash[:success] = t('success.profile_save')
    sign_in @user
    redirect_to @user
  else
    flash.now[:error] = t('error.profile_save')
    render 'edit'
  end
end

解决方案

decrement! calls save which of course fires save callbacks. It looks like the book directs you to do

before_save :create_remember_token
def create_remember_token
  self.remember_token = SecureRandom.urlsafe_base64
end

which means that saving a user will always invalidate the remember token. I assume this is so that when a user changes their password the remember token changes too, but it means that there is obviously some collateral damage.

You could use the decrement_counter which in essence does

update users set counter_name = counter_name - 1 where id =12345

without running any callbacks. This also avoids some race condition scenarios. However changing the token whenever the user changes is bound to change the token at times when you don't expect it - you might want to only change it when relevant (perhaps when credentials have changed)

这篇关于ActiveRecord的方法递减!更新其他属性也是如此。这是为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆