使用嵌套资源在会话中存储参数
Storing Params in a Session with Nested Resource
我正在使用 Rails 4.
我在文章中嵌套了子文章。当用户需要在提交前创建帐户时,我将子文章中的所有表单数据存储在会话中。
这是我正在使用的 (subarticles_controller):
def create
if current_user.nil?
session[:subarticle] = params
redirect_to new_user_session_path
end
然后在用户注册后,它使用
创建带有存储参数的子文章
if session[:subarticle].present?
@subarticle = current_user.subarticles.create(session[:subarticle]["subarticle"])
session[:subarticle] = nil
flash[:notice] = "Awesome, you are logged in and your answer is undergoing review."
edit_user_registration_path
end
但是,我在保存创建子文章的 article_id 时遇到了问题。有人可以指出我这样做的正确方向吗?
更好的方法是将来宾用户创建的(子)文章保存在数据库中。
class SubArticlesController < ApplicationController
before_action :set_article, only: [:show, :edit, :update, :destroy]
# ...
def create
@subarticle = Article.new(article_params) do |a|
if current_user
a.user = current_user
else
a.token = SecureRandom.hex
end
end
if @subarticle.save
if @subarticle.user
redirect_to @subarticle
else
session[:after_sign_in_path] = edit_article_path(@subarticle, token: @subarticle.token)
redirect_to new_user_session_path, notice: 'Please sign in to finalize your article.'
end
else
render :new
end
end
def edit
if @subarticle.user.nil? && @subarticle.token != params[:token]
redirect_to root_path, alert: 'You are not authorized.'
end
flash[:notice] = 'Please press save again to publish your post.' unless @subarticle.user
render :edit
end
def update
# The @subarticle.token should be included in the edit form
unless @subarticle.user && @subarticle.token == params[:sub_article][:token]
# let the current user claim the article
@subarticle.user = current_user
end
if @subarticle.update(article_params)
redirect_to @subarticle
else
render :edit
end
end
private
def set_article
@subarticle = Article.find(params[:id])
end
def sub_article_params
params.require(:sub_article).permit(...)
end
end
所以在这里我们改为给用户 link 到文章的编辑页面,其中 he/she 可以 "finish" 登录后的文章。
由于恶意用户可能 "steal" 通过猜测 id 并输入编辑 url 无人认领的文章,我们添加了一个随机令牌,我们将其与文章一起存储在数据库中并添加到 url。不是 100% 万无一失,但至少更好。
要完成这项工作,您还需要在表单中添加一个令牌字段:
<%= form_for(@subarticle) do |f| %>
...
<%= f.hidden_field :token %>
...
<% end %>
您可能要考虑这一点的原因是因为会话存储通常是基于内存的,如果您有大量流量,将整个参数哈希存储在会话中会耗尽服务器内存。此外,您应该在用户登录或注销之前重置会话以避免会话固定。
不过我们确实有一些问题 - 首先,如果用户(或机器人)从未登录,我们不想积累一堆 "unclaimed" 文章。最简单的方法是设置 cron 作业以删除超过特定年龄且没有关联用户的文章。
您还希望通过 show/index 操作过滤任何没有用户的文章。
我正在使用 Rails 4.
我在文章中嵌套了子文章。当用户需要在提交前创建帐户时,我将子文章中的所有表单数据存储在会话中。
这是我正在使用的 (subarticles_controller):
def create
if current_user.nil?
session[:subarticle] = params
redirect_to new_user_session_path
end
然后在用户注册后,它使用
创建带有存储参数的子文章if session[:subarticle].present?
@subarticle = current_user.subarticles.create(session[:subarticle]["subarticle"])
session[:subarticle] = nil
flash[:notice] = "Awesome, you are logged in and your answer is undergoing review."
edit_user_registration_path
end
但是,我在保存创建子文章的 article_id 时遇到了问题。有人可以指出我这样做的正确方向吗?
更好的方法是将来宾用户创建的(子)文章保存在数据库中。
class SubArticlesController < ApplicationController
before_action :set_article, only: [:show, :edit, :update, :destroy]
# ...
def create
@subarticle = Article.new(article_params) do |a|
if current_user
a.user = current_user
else
a.token = SecureRandom.hex
end
end
if @subarticle.save
if @subarticle.user
redirect_to @subarticle
else
session[:after_sign_in_path] = edit_article_path(@subarticle, token: @subarticle.token)
redirect_to new_user_session_path, notice: 'Please sign in to finalize your article.'
end
else
render :new
end
end
def edit
if @subarticle.user.nil? && @subarticle.token != params[:token]
redirect_to root_path, alert: 'You are not authorized.'
end
flash[:notice] = 'Please press save again to publish your post.' unless @subarticle.user
render :edit
end
def update
# The @subarticle.token should be included in the edit form
unless @subarticle.user && @subarticle.token == params[:sub_article][:token]
# let the current user claim the article
@subarticle.user = current_user
end
if @subarticle.update(article_params)
redirect_to @subarticle
else
render :edit
end
end
private
def set_article
@subarticle = Article.find(params[:id])
end
def sub_article_params
params.require(:sub_article).permit(...)
end
end
所以在这里我们改为给用户 link 到文章的编辑页面,其中 he/she 可以 "finish" 登录后的文章。
由于恶意用户可能 "steal" 通过猜测 id 并输入编辑 url 无人认领的文章,我们添加了一个随机令牌,我们将其与文章一起存储在数据库中并添加到 url。不是 100% 万无一失,但至少更好。
要完成这项工作,您还需要在表单中添加一个令牌字段:
<%= form_for(@subarticle) do |f| %>
...
<%= f.hidden_field :token %>
...
<% end %>
您可能要考虑这一点的原因是因为会话存储通常是基于内存的,如果您有大量流量,将整个参数哈希存储在会话中会耗尽服务器内存。此外,您应该在用户登录或注销之前重置会话以避免会话固定。
不过我们确实有一些问题 - 首先,如果用户(或机器人)从未登录,我们不想积累一堆 "unclaimed" 文章。最简单的方法是设置 cron 作业以删除超过特定年龄且没有关联用户的文章。
您还希望通过 show/index 操作过滤任何没有用户的文章。