【发布时间】:2016-09-13 19:35:14
【问题描述】:
我的 Rails 应用程序依赖 Rails 缓存来临时保存用户输入并在用户登录过程中在控制器操作之间传递它。但是,我意识到我犯了一个非常严重的错误(因为我通常是 Rails 和 MVC 的超级新手)并且可以使用一些帮助/建议/智慧 - 基本上,如果两个用户同时(或几乎同时)提交数据并通过下面的控制器步骤,会有一些麻烦 - 丢失数据,一个用户的数据被输入为另一个,等等。当我构建这个时,我不了解控制器的性质,虽然我肯定有现在更好的主意....
简而言之,以下代码的工作方式如下:未登录用户填写表单并提交数据,该数据被传递给submission 操作并保存在名为@987654323 的Rails 缓存对象中@;然后提示用户登录(通过 Devise),成功登录会触发 approval 控制器操作,该操作读取 incoming_report 缓存对象,将该数据保存到数据库,然后创建一个名为 @ 的新缓存对象987654326@ 挂在用户条目的 id # 上;这将重定向到 summary 操作,该操作收集这些 id 并将相应的数据显示给用户作为其条目的摘要。
report_controller.rb
#ON SUBMITTING THE FORM...
def submission
@incomingReport = ActiveSupport::JSON.decode(params[:report])
#SUBMITTED DATA IS HELD IN THE CACHE AS 'incoming_report' TO PASS TO approval CONTROLLER ACTION ON SUCCESSFUL LOGIN
Rails.cache.write("incoming_report",@incomingReport)
end
#ON SUCCESSFUL LOG IN...
def approval
@incomingReport = Rails.cache.read("incoming_report")
@newReportIDArray = Array.new
@incomingReport.each do |x|
#DATA PROCESSING STUFF HERE...
end
#DELETE 'incoming_report' FROM CACHE
Rails.cache.delete("incoming_report")
#ID NUMBERS OF ENTRIES ARE HELD TO PASS TO summary CONTROLLER ACTION
Rails.cache.write("ids",@newReportIDArray)
redirect_to report_summary_path
end
#AFTER DATA IS ENTERED...
def summary
@newReportIDs = Rails.cache.read("ids")
#DELETE 'ids' FROM CACHE
Rails.cache.delete("ids")
end
在大多数情况下,这很有效,但如果用户在任何这些操作中相互交叉,那将是灾难性的。例如,如果一个用户在另一个用户忙于登录时点击了submission 操作,则第二个用户的incoming_report 对象将覆盖第一个用户的对象......等等。
这个问题的主要来源是用户在单击表单提交按钮后登录 - 应用程序必须以这种方式构建 - 并且数据不能保存在本地/会话存储对象中,因为它包含base64 字符串,并且太长而无法在某些浏览器中使用这些方法。在我注意到这个问题之前,将这些数据保存在服务器上似乎是最好的做法......
有什么方法可以防止用户在控制器中互相干扰?还是我犯了一个非常致命的错误?
编辑以显示解决方案
最终,使用会话变量而不是 Rails 缓存节省了一天的时间。这是重新配置的控制器以显示解决方案...
def submission
@incomingReport = ActiveSupport::JSON.decode(params[:report])
@newReportIDArray = Array.new
@incomingReport.each do |x|
#DATA PROCESSING STUFF HERE
@newReportIDArray.push(@new_report.id)
end
session[:ids] = @newReportIDArray
respond_to do |format|
format.json do
render json: {
success: 200
}.to_json
end
end
end
def approval
@reportIDs = session[:ids]
@reportIDs.each do |x|
@new_report = Report.find(x)
@new_report.user_id = current_user.id
@new_report.save
end
redirect_to report_summary_path
end
def summary
@reportIDs = session[:ids]
end
非常感谢在这方面帮助我并向我展示会话变量的方式的两个人。
我遇到了会话变量在控制器操作之间“丢失”的问题 - Rails / Devise - updating session variables between controller actions
【问题讨论】:
-
您应该使用特定于浏览器的会话而不是缓存。
-
@JohnNaegle 谢谢!你和 Wade73 给了我很好的思考。
-
@JohnNaegle 太棒了,谢谢你的建议。我不得不稍微修改一下逻辑,但使用会话变量完全解决了我的问题。
标签: ruby-on-rails ruby ruby-on-rails-4