奇怪的行为:关闭帐户所需的重新加载

时间:2016-01-20 14:41:43

标签: ruby-on-rails ruby ruby-on-rails-4

要停用帐户,我的方法类似于:

def closing         # Controller method
  @user = current_user
  relationships = @user.relationships
  relationships.each { |relationship| relationship.destroy }
  log_out
end

def log_out         # In sessions helper
  forget(current_user)
  session.delete(:user_id)
  @current_user = nil
end

def forget(user)    # In sessions helper
  debugger
  user.forget       # If I change this to user.reload.forget the error below is gone
  cookies.delete(:user_id)
  cookies.delete(:api_token)
end

def forget          # In User table
  update_attributes(remember_digest: nil, email_digest: nil)
end

但是,关闭帐户会为行user.forget生成错误消息:

  

ActiveRecord :: RecordNotFound:无法找到与之关系   ' id' = 129095216 [地点"人际关系"。" user_id" =?]

在上面的代码中查看debugger的位置。我使用调试器查看user的值:字段default_relationship_id仍然具有值129095216。如果我输入user.reload,则default_relationship_id的值确实为nil。事实上,将会话助手中的那一行重写为user.reload.forget,一切正常。

然而,重新加载不是必要的。事实上,在过去它曾经工作过,我一直在改变一些代码,但不了解这些行为。一定有什么问题,因为重新加载不是必要的。该怎么办?是什么导致了这种行为?

有关该关联的更多信息(从上述错误出现之后,此代码未进行任何更改):

用户模型:

has_many   :relationships, dependent: :destroy, inverse_of: :user
has_many   :organizations, through: :relationships, inverse_of: :users
belongs_to :default_relationship, class_name: "Relationship", foreign_key: :default_relationship_id, inverse_of: :default_for_user
has_one    :default_organization, through: :default_relationship, source: :organization

关系模型:

belongs_to :user,         :inverse_of => :relationships
belongs_to :organization, :inverse_of => :relationships
has_one    :default_for_user, class_name: "User", foreign_key: :default_relationship_id, inverse_of: :default_relationship, dependent: :nullify

1 个答案:

答案 0 :(得分:1)

尝试删除存储在会话中的cookie和/或值是一种有缺陷的方法。相反,您应该使用reset_session - 它使当前会话标识符无效并发出新标识符。

def log_out         # In sessions helper
  reset_session
  @current_user = nil
end

因此,即使用户仍然有一个指向其先前会话的cookie,Rails也不会加载会话。

在内存中与数据库中。

@user = current_user
relationships = @user.relationships
relationships.each { |relationship| relationship.destroy }

请注意,在此代码中,您在User中存储@user对象,在ActiveRecord::Relation中存储relationships对象 - 这些对象都存储在服务器内存中。当您遍历relationships并销毁每个时,您不会更新@user中存储在内存中的值。这就是为什么需要.reload - 它用数据库中的表示刷新过时的@user对象。

相反,您应该使用destroy_all,因为它会产生更有效的数据库查询,并且使用的内存少于迭代每个项目。

def closing         # Controller method
  @user = current_user
  @user.relationships.destroy_all
  @user = @user.reload
end