Rails:从控制器调用另一个控制器动作

dda*_*yan 109 ruby-on-rails

我需要从控制器B调用控制器A中的create动作.

原因是当我从控制器B呼叫时,我需要以不同的方式重定向.

可以在Rails中完成吗?

Spy*_*ros 63

您可以使用重定向到该操作:

redirect_to your_controller_action_url
Run Code Online (Sandbox Code Playgroud)

更多信息:Rails指南

要呈现新动作:

redirect_to your_controller_action_url and return
Run Code Online (Sandbox Code Playgroud)

  • 对不起,你能说出第一行和第二行有什么区别吗?我认为首先将执行剩余的代码行,然后重定向.那是对的吗? (4认同)
  • 嗨@spyros,`redirect_to` 不允许使用`post::method`,这对于重定向到另一个控制器已经存在的`create` 动作特别有用,正如@ddayan 第一次询问的那样。我有一个类似的情况,在某些情况下我应该创建另一个对象。调用另一个 `create` 动作可以是 DRYer.. (2认同)

Sam*_*rbi 46

要使用另一个控制器,请执行以下操作:

def action_that_calls_one_from_another_controller
  controller_you_want = ControllerYouWant.new
  controller_you_want.request = request
  controller_you_want.response = response
  controller_you_want.action_you_want
end
Run Code Online (Sandbox Code Playgroud)

  • 如果你想要在`controller_you_want`中执行回调,你会做`controller_you_want.process(:action_you_want)` (14认同)
  • 谢谢!这对于您不想重定向的情况非常有用,您只需要一个快速的解决方案来采用从一个控制器到另一个控制器的操作.重定向真的是不同的东西.另外:`render status :: ok,json:JSON.parse(controller.render(:action_you_want).first)`似乎可以从其他控制器返回JSON (3认同)

apn*_*ing 40

你提出的逻辑不是MVC,而是Rails,兼容.

  • 控制器呈现视图或重定向

  • 方法执行代码

从这些考虑,我建议您在控制器中创建方法并从您的操作中调用它们.

例:

 def index
   get_variable
 end

 private

 def get_variable
   @var = Var.all
 end
Run Code Online (Sandbox Code Playgroud)

也就是说你可以通过不同的控制器做同样的事情,并在控制器B中召唤控制器A 的方法.

词汇非常重要,这就是我坚持的原因.

  • 喜欢它..从渲染中分离出方法,然后在需要的地方调用单独的方法.只有一个问题..现在如何从另一个控制器调用`get_variable`? (9认同)
  • 喜欢这个答案,不确定后面的句子片段 (2认同)

aus*_*tin 30

您可以使用url_for获取控制器和操作的URL,然后使用redirect_to该URL转到该URL.

redirect_to url_for(:controller => :controller_name, :action => :action_name)
Run Code Online (Sandbox Code Playgroud)

  • @msanjay你可以将它们作为其他参数传递给url_for.例如`redirect_to url_for(:controller =>:controller_name,:action =>:action_name,:param1 =>:val1,:param2 =>:val2)`将导致`/ contorller_name/action_name?param1 = val1&param2 = val2` .参见[文档](http://api.rubyonrails.org/classes/ActionDispatch/Routing/UrlFor.html) (3认同)
  • 另一个似乎不适合我,这个看起来更好,但是我们如何传递参数呢? (2认同)

fl0*_*00r 12

调用另一个控制器操作是不好的做法.

你应该

  1. 在控制器B中复制此操作,或
  2. 将其包装为模型方法,将共享给所有控制器,或
  3. 你可以在控制器A中扩展这个动作.

我的看法:

  1. 第一种方法不是DRY,但它仍然比要求另一种行动更好.
  2. 第二种方法是好的和灵活的.
  3. 第三种方法是我过去经常做的事情.所以我会举一些例子.

    def create
      @my_obj = MyModel.new(params[:my_model])
      if @my_obj.save
        redirect_to params[:redirect_to] || some_default_path
       end
    end
    
    Run Code Online (Sandbox Code Playgroud)

所以你可以发送到这个动作redirect_to参数,它可以是你想要的任何路径.


Mic*_*ant 6

也许逻辑可以被提取到帮助器中?助手可用于所有类,不转移控制.您可以在其中检查,可能是控制器名称,以查看它是如何被调用的.


Ole*_*yev 5

组成救援!

鉴于原因,不应该跨控制器调用操作,而应设计控制器以分离代码的共享和自定义部分.这将有助于避免代码重复和破坏MVC模式.

尽管可以通过多种方式完成,但使用关注点(组合)是一种很好的做法.

# controllers/a_controller.rb
class AController < ApplicationController
  include Createable

  private def redirect_url
    'one/url'
  end
end

# controllers/b_controller.rb
class BController < ApplicationController
  include Createable

  private def redirect_url
    'another/url'
  end
end

# controllers/concerns/createable.rb
module Createable
  def create
    do_usefull_things
    redirect_to redirect_url
  end
end
Run Code Online (Sandbox Code Playgroud)

希望有所帮助.