Ruby on rails 如何重定向以创建另一个控制器的操作

Ruby on rails 如何重定向以创建另一个控制器的操作,ruby-on-rails,redirect,omniauth,Ruby On Rails,Redirect,Omniauth,我知道我不能发布HTML重定向,但我的情况要求我在验证用户身份后重定向以创建操作。我想知道如何绕过这个限制: 特别是,我希望允许用户在不使用Omniauth登录的情况下填写帖子。我使用AJAX调用将post保存到会话[:post]。然后,用户可以使用omniauth登录并持久化帖子 我有一个带有创建操作的PostsController,它可以处理初始ajax调用,还可以在验证用户身份后处理html请求: def create @post = Post.new(params[:

我知道我不能发布HTML重定向,但我的情况要求我在验证用户身份后重定向以创建操作。我想知道如何绕过这个限制:

特别是,我希望允许用户在不使用Omniauth登录的情况下填写帖子。我使用AJAX调用将post保存到会话[:post]。然后,用户可以使用omniauth登录并持久化帖子

我有一个带有创建操作的PostsController,它可以处理初始ajax调用,还可以在验证用户身份后处理html请求:

  def create    
    @post = Post.new(params[:post])   
    respond_to do |format|    
      format.html{
        if @post.save
          redirect_to @post, notice: 'Post was successfully created.'
        else
          render action: "new"
        end
      }
      format.json {
        if session[:post] = @post
          render json: @post, status: :created, location: @post
        else
          render json: @post.errors, status: :unprocessable_entity
        end
      }
    end
  end
end 
然后,在我处理Facebook回调的控制器中,我有:

class ServicesController < ApplicationController
  def create
    ... authentication logic here ...
    sign_in(:user, service.user)
    redirect_to :controller => "posts", :action =>"create"
  end
  method_alias: :facebook, :create
class-ServicesController“posts”,:action=>“create”
结束
方法\u alias::facebook,:创建

但是,这不起作用,因为我无法重定向到“创建”操作。如何完成此任务?

在您发布的代码中,您从未阅读过会话内容。我认为,如果您使用以下方法更改代码,它可以工作:

更改
@post
的初始化:

@post = Post.new(params[:post]) || session[:post]  # Find object in session if not 
并在
post.save
之后添加:

session.delete :post   # clean session after successful creation
新的完整方法:

  def create    
    @post = Post.new(params[:post]) || session[:post]  # Find object in session if not in params  
    respond_to do |format|    
      format.html{
        if @post.save
          redirect_to @post, notice: 'Post was successfully created.'
          session.delete :post   # clean session after successful creation
        else
          render action: "new"
        end
      }
      format.json {
        if session[:post] = @post
          render json: @post, status: :created, location: @post
        else
          render json: @post.errors, status: :unprocessable_entity
        end
      }
    end
  end
end

您可以在Post模型上创建一个方法,并从PostsController和ServicesController中调用它来保存Post(尽管在这种情况下,它非常简单:新建,然后保存,因此在DRY方面没有任何效果,这可能是一些封装好处)。或者创建一个包含create_post方法和所有逻辑的公共mixin。然后将其包含到SessionController和PostsController中,并从“create”调用它

在mixin模块中:

def create_post(allow_json=false)
  @post = Post.new(params[:post])   
  respond_to do |format|    
    format.html {
      if @post.save
        redirect_to @post, notice: 'Post was successfully created.'
      else
        render "posts/new"
      end
    }
    if allow_json
      ... your post-saving & json-processing logic ...
    end
  end
end
在PostsController中:

def create
  create_post(true)
end
def create
  ... authentication logic here ...
  sign_in(:user, service.user)
  create_post(false)
end
sign_in(:user, service.user) 
redirect_to persist_posts_path
在会话控制器中:

def create
  create_post(true)
end
def create
  ... authentication logic here ...
  sign_in(:user, service.user)
  create_post(false)
end
sign_in(:user, service.user) 
redirect_to persist_posts_path

我没有编译和尝试,所以我只希望它能工作。总的来说,我必须说有一些基本上是错误的,所以我会寻找其他架构解决方案来实现相同的结果,但作为一种快速而肮脏的方法,它可能会起作用。

我找到了一种解决方法来避免这个问题:我让#create处理AJAX调用并写入会话,然后创建另一个操作,在用户获得身份验证后将其持久保存到我的数据库中:

class PostsController < ApplicationController

  def create  
    @post = Post.new(params[:post])    
    respond_to do |format|
      format.json {
        if session[:post] = @post
          render json: @post, status: :created, location: @post
        else
          render json: @post.errors, status: :unprocessable_entity
        end
      }
    end
  end

  def persist
    @post = session[:post]
    if @post.save
       session.delete :post
       redirect_to @post, notice: 'Post was successfully created.'
     else
       render action: "new"
     end
  end
最后,在我的ServicesController中:

def create
  create_post(true)
end
def create
  ... authentication logic here ...
  sign_in(:user, service.user)
  create_post(false)
end
sign_in(:user, service.user) 
redirect_to persist_posts_path

我想is是
render action=>:create
,但我正在苦苦寻找它的文档。@Cort3z:如果您能找到,我将不胜感激。我也会找的。你应该创建一个答案,而不是编辑你的问题,这样对未来的访问者来说会更具可读性。查看下面的url,了解如何添加
持久化
路由而不出现错误(在您的情况下使用收集路由):@Baldrick:非常感谢您提供有关收集路由的提示。我将修改我的代码并将其添加为答案。不客气。现在你可以接受自己的答案了,这是第一个可见的答案。谢谢你指出错误。然而,我收到的错误消息是因为我无法重定向到创建操作,因为这是一篇文章。我从来没有改变过#通过HTML请求创建:)@Cort3z我认为重点不在于显示视图,而在于通过渲染可以做什么(渲染“posts/new”,我相信这里的“posts/create”是一个POST请求,没有视图),而是实际创建POST(它只存储在会话中,而不是最初以format.json块的形式在db中创建)。因此,渲染不是您所需要的。重定向到,嗯,无法重定向到POST请求,因此您最终会对您的体系结构执行一些操作以实现相同的结果。感谢您的回答。创建一个模块以在两个控制器之间共享一种方法对我来说是一个新的学习。但是,这可能表明他从根本上说有问题回复:)。我提出了另一种解决方案,可以避免像您建议的第一种方法那样从两个控制器调用方法(请参阅我的更新)。