创建一个对象并在一个请求中更新另一个对象

时间:2014-06-24 16:39:06

标签: ruby-on-rails

在我的Rails应用程序中,我想在用户登录后执行某些操作。例如:

  • 用户正在浏览该网站。他没有登录。
  • 用户在网站上创建新对象。由于用户未登录,因此该对象是公开可见的。
  • 用户现在想要将对象设为私有。他点击“make private”按钮。
  • 由于他未登录,因此该网站不知道将私人对象与谁关联。它会将他重定向到登录表单。
  • 用户登录他的帐户。这使用标准的RESTful POST请求来登录。然后 - 这是我需要帮助的部分 - 它还更新对象以使其成为私有。然后它将他重定向回(现在是私有的)对象视图。

我是Rails的新手,但我的理解是我无法从登录控制器向其他对象控制器发送PUT请求,因为重定向不允许您POST数据。

我想我也可以在登录路径中放置一些GET变量(即http://example.com/login?ref=123&action=make_private),登录控制器可以将其解释为“使ID为123的私有对象”。无论何时创建新登录,登录控制器都可以检查这些参数的存在,并处理该对象本身的更新。但似乎必须有一种更好的方法,而不是将更新操作从对象的控制器复制到登录控制器。

我想到的最后一个选项是更改工作流程,以便用户只需看到“登录以进行更新”按钮,而不是看到“设置私人”按钮,但将这些操作分开比分开只需点击一下即可使它们成为可能,所以我宁愿这样做只是作为最后的手段。

我忽略了什么吗?做这样的事情的正确方法是什么(如果正确的方式)?

2 个答案:

答案 0 :(得分:1)

我看到你在问什么,所以我会试着踩过你。

在用户点击“make private”时,有一个已经创建的对象,对吗?假设是这样,那么当未登录的用户被重定向到登录页面时,只需将该对象id和“make private”命令一起传递。这意味着您应该有一个包含以下内容的参数列表:object_id => "1", method => "make_private"

现在您可以选择,您可以通过执行以下操作更新检查中的对象以获取您应该已有的有效登录方法:

if params[:object_id] && params[:method] == "make_private"
  #make object private
  redirect_to objects_path(params[:object_id])
else 
  #normal login redirect
end

或者您可以将登录确认方法重定向到对象的更新方法,并从其重定向到对象的视图页面,如下所示:

def login_validation
  #normal login checking
  if params[:object_id] && params[:method] == "make_private"
    redirect_to object_path(params[:object_id])
  else
    #redirect to normal after login page
  end
end

然后在您的更新中,您需要:

def update
  #normal update stuff   
  redirect_to objects_path(params[:object_id])
end  

显然你需要能在你的更新方法中检测“make private”命令的东西,但这不应该太难。如果您需要帮助,请在此处发表评论,我也会为此添加相关说明。

更新: 如果你真的想要想象,你可以将重定向路径本身传递给登录功能,然后只需重定向到提供的登录路径。

例如,您的私人按钮可能如下所示

<%= button_to "Make Private", object_path(:id=>object_id) %>

然后它会尝试更新,意识到它没有登录用户,并重定向到登录页面如下:

def update
  if user_logged_in?
    #do normal update stuff
  else
    redirect_to login_path(:redirect_path => object_path(params[:id])
end

然后他们会填写他们的正常信息,当他们点击确认它会有一个额外的参数如下:

<%= button_to "Confirm", login_validation_path(<normal login params>,params[:redirect_path]) %>

然后在您的login_validation中,您将进行正常的验证,然后重定向到您给出的任何路径。

def login_validation
  #normal login stuffs
  if params[:redirect_path]
    redirect_to params[:redirect_path]
  else
    #normal redirect
end

这样您的登录就可以处理从多个不同位置调用并正确地重定向到您想要的位置。

答案 1 :(得分:0)

您可以通过只是在创建用户的操作中更新对象来实现它,但您必须将您的对象ID发送到您的创建操作 这样您就可以更新该对象并将其设为私有。

def create
  @user = User.new user_params
  if @user.save
    @object = Object.find(params[:object_id])
    @object.update_attributes(:private => true)
  else
    render new
  end
end

您还可以使用有效记录after_create callback

class User < ActiveRecord::Base
  after_create :update_object

  def update_object
    #your logic to update object
  end
end

<强>更新

如果您想在用户登录后更新您的对象,则可以执行以下操作:

一个。创建发送发布请求 的路线,以便您可以发送您的对象ID

post '/object/:id' => "your_controller#update_object", as: 'update_object'

湾设置链接以更新该对象

<%= link_to "object", update_object_path(@object.id), method: :post %>

℃。在方法中更新您的对象:

def update_object
  @object = Object.find(params[:id])
  @object.update_attributes(:private => true)
  redirect_to your_path, notice: "object made private"
end

如果您使用设计进行身份验证,则可以通过 current_user获取用户,如果您拥有自定义身份验证,那么可以创建一种方法来查找当前用户

 class ApplicationController < ActionController::Base
   def current_user
     @current_user ||= User.find(session[:user_id])
   end
 end