Ruby on rails 什么';在没有HTTP重定向的情况下,从另一个控制器操作运行一个控制器操作的正确方法是什么?
我希望能够根据查询参数和数据库中数据的组合,有条件地从一个控制器动作分派到另一个控制器动作 我现在的情况是:Ruby on rails 什么';在没有HTTP重定向的情况下,从另一个控制器操作运行一个控制器操作的正确方法是什么?,ruby-on-rails,Ruby On Rails,我希望能够根据查询参数和数据库中数据的组合,有条件地从一个控制器动作分派到另一个控制器动作 我现在的情况是: class OldController < ApplicationController def old_controller_action if should_use_new_controller new_params = params.dup new_params[:controller] = "new_controller_action"
class OldController < ApplicationController
def old_controller_action
if should_use_new_controller
new_params = params.dup
new_params[:controller] = "new_controller_action"
redirect_to new_params
return
end
# rest of old and busted
end
end
class NewController < ApplicationController
def new_controller_action
# new hotness
end
end
class OldController
这工作得很好,但它会发出HTTP重定向,速度很慢。我希望能够做同样的事情,但在相同的HTTP请求中
有没有干净的方法可以做到这一点
编辑:赏金将授予某人,他可以向我展示一种干净的方法,使控制器及其操作相对不受影响(重定向代码本身除外)。与其跨操作调用代码,不如将代码提取到lib/或其他什么,然后从两个控制器调用该代码
# lib/foo.rb
module Foo
def self.bar
# ...
end
end
# posts_controller
def index
Foo.bar
end
# things_controller
def index
Foo.bar
end
创建控制器类的实例:
@my_other_controller = MyOtherController.new
然后对其调用方法:
@my_other_controller.some_method(params[:id])
我更喜欢模块的想法,但这应该可以做到
还可以从另一个控制器整体传递参数:
@my_other_controller.params = params
我想你想要选项3,但让我们先看一些备选方案 选项1-将控制器选择逻辑推送到一个助手中,该助手将正确的链接插入到视图中。好处-控制器保持干净,缺点-如果决策逻辑取决于提交的值,这种方法将不起作用。如果URL被外部网站调用,那么这将不起作用 选项2-将逻辑推回到您的模型中。专业的-保持控制器清洁。缺点-如果你有很多sesson、params或render/redirect_到交互,那么它就不能正常工作 选项3保持在同一控制器内。我怀疑您试图用一些新功能替换一些现有功能,但仅在某些情况下。专业的-简单,有权访问您需要的一切。Cons-仅在使用同一控制器有意义时有效,即您与同一实体(如用户、地点或公司)合作 让我们看一个选项3的示例。我的链接控制器与其他用户的管理员行为完全不同
class LinksController < ApplicationController
#...
def new
#Check params and db values to make a choice here
admin? ? new_admin : new_user
end
#...
private
def new_admin
#All of the good stuff - can use params, flash, etc
render :action => 'new_admin'
end
def new_user
#All of the good stuff - can use params, flash, etc
render :action => 'new_user'
end
end
类链接控制器“新建管理员”
结束
def新用户
#所有的好东西-可以使用params、flash等
render:action=>“新用户”
结束
结束
如果两个控制器尝试执行相同的操作,则很有可能在一个模型中执行此操作。仔细看看您的设计,很抱歉,我不知道您在MVC方面的经验水平,请阅读瘦控制器技术:
如果问题是您需要另一个控制器来进行渲染,那么可能路线应该首先指向那里,而skinny controller技术仍然可以节省时间。执行以下操作:
class OldController < ApplicationController
def old_controller_action
if should_use_new_controller
new_controller_action
end
# rest of old and busted
end
end
class OldController
还有新的控制器
class NewController < OldController
def new_controller_action
# new hotness
end
end
class NewController
如果将控制器之间的公共代码提取到模块中对您不起作用,我将使用机架中间件。我没有看到在中间件中使用ActiveRecord
的代码,但我不知道为什么不可能,因为人们使用了Redis
等
否则,我认为您唯一的选择是使用类似(未测试,伪示例)的内容重新启动请求处理:
这类似于集成测试的实现方式。但是我不知道从调用
到你点击一个控制器,所有的事情是否都是幂等的,并且可以像这样安全地重新运行。你可以通过追踪源代码来查看。但即使现在一切正常,它也有可能在rails或rack的任何未来版本中崩溃
使用中间件可以在请求运行之前拦截请求,从而避免这种情况。通过将代码提取到包含在这两个地方的通用模块中,您应该仍然能够与rails应用程序共享代码
老实说,我认为仅仅做普通控制器代码的分解这件简单的事情可能更干净,但是如果没有您的详细情况,很难知道,所以我想我会继续提出这个建议。是的,我也想到了这个,尽管这不是一个非常令人兴奋的选择,从代码组织的角度来看,这实际上是可以的,因为它创建了从两个地方调用的内聚方法,这很容易测试,但效果不太好。很难在控制器的这个新实例中调用“render”方法。如果在原始控制器中调用render,则将丢失在被调用控制器中设置的所有变量。Jarrod-controller=sessioncontroller.new post controller.create如何在此create方法中传递参数。比如用户名和密码?
env['REQUEST_URI'] = new_controller_uri_with_your_params
call(env)