Ruby on rails 在具有嵌套资源的会话中存储参数

Ruby on rails 在具有嵌套资源的会话中存储参数,ruby-on-rails,forms,ruby-on-rails-4,parameters,controller,Ruby On Rails,Forms,Ruby On Rails 4,Parameters,Controller,我使用的是Rails 4 我在文章中嵌套了子文章。当用户需要在提交之前创建帐户时,我将在会话中存储子节中的所有表单数据 以下是我正在使用的(子节\控制器): 然后,在用户注册之后,它使用 if session[:subarticle].present? @subarticle = current_user.subarticles.create(session[:subarticle]["subarticle"]) session[:subarticle] = nil flash[

我使用的是Rails 4

我在文章中嵌套了子文章。当用户需要在提交之前创建帐户时,我将在会话中存储子节中的所有表单数据

以下是我正在使用的(子节\控制器):

然后,在用户注册之后,它使用

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

但是,我在保存创建子篇的文章_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
class SubticlesController
因此,我们在这里为用户提供了一个指向文章编辑页面的链接,用户可以在登录后“完成”文章

由于恶意用户可能通过猜测id并输入编辑url来“窃取”无人认领的文章,因此我们添加了一个随机令牌,将其与文章一起存储在数据库中并添加到url中。不是100%万无一失,但至少更好

要实现此功能,您还需要在表单中添加一个令牌字段:

<%= form_for(@subarticle) do |f| %>
  ...
  <%= f.hidden_field :token %>
  ...
<% end %>

...
...
<> P>您可能想考虑这一点是因为会话存储通常是基于内存的,并且如果有大量的流量存储,会话中的整个PARAMS散列将耗尽服务器内存。此外,您还应在用户登录或注销之前重置会话,以避免会话固定

不过,我们确实有一些问题——首先,如果用户(或机器人)从未登录,我们不想积累一堆“无人认领”的文章。最简单的方法是设置一个cron作业,在没有关联用户的情况下删除超过一定年龄的文章


您还希望从show/index操作中筛选没有用户的任何文章

是否将(父)项保存到数据库中?当然,如果不使用HTTPS,令牌在URL中仍然容易受到中间人攻击的影响。不过,这可能是“足够好”的安全性。非常感谢您的深入回答和推荐更好的解决方案。我很可能会走这条路,但是如果我想继续我的路,我怎么才能把文章ID保存在那里呢?我的目标是稍后调用
subtitle.article.title
,但我收到一个错误,因为它找不到文章。此外,我不必担心有人偷了一篇文章,因为用户在提交后无法编辑文章(cancancan)。应该说得更清楚。再次感谢你@max您必须先将其保存到数据库才能获得id-ActiveRecord中的id只是自动递增的数据库列。
<%= form_for(@subarticle) do |f| %>
  ...
  <%= f.hidden_field :token %>
  ...
<% end %>