1

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

特别是,我希望允许用户在不使用 Omniauth 登录的情况下填写帖子。我使用 AJAX 调用将帖子保存到 session[: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

但是,这不起作用,因为我无法重定向到“创建”操作。我怎样才能完成这项任务?

4

3 回答 3

1

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

在混合模块中:

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

在 SessionsController 中:

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

我没有编译和尝试,所以我只希望它有效。总的来说,我必须说基本上是错误的,所以我会寻找其他架构解决方案来达到相同的结果,但作为一种快速而简单的方法,它应该可以工作。

于 2013-02-27T20:53:08.463 回答
1

我发现了一个避免此问题的技巧:我让#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

然后在我的 routes.rb 中,我有:

  resources :posts do
    collection do
      get 'persist'
    end
  end

最后,在我的 ServicesController 中:

sign_in(:user, service.user) 
redirect_to persist_posts_path
于 2013-02-27T21:28:54.627 回答
1

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

更改初始化@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
于 2013-02-27T20:45:33.310 回答