Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 使用机架中间件的参数调用控制器操作_Ruby On Rails_Ruby_Rack - Fatal编程技术网

Ruby on rails 使用机架中间件的参数调用控制器操作

Ruby on rails 使用机架中间件的参数调用控制器操作,ruby-on-rails,ruby,rack,Ruby On Rails,Ruby,Rack,有没有一种方法可以将参数从中间件传递给控制器操作调用 这是控制器代码中的操作 # in my_controller.rb # def print_name(name) render :text => "Hello, #{name}!" end 下面是我的中间件中调用此操作的代码 # in middleware # def call(env) env['action_controller.instance'].class.action(:print_name).call(en

有没有一种方法可以将参数从中间件传递给控制器操作调用

这是控制器代码中的操作

# in my_controller.rb
# 
def print_name(name)
    render :text => "Hello, #{name}!"
end
下面是我的中间件中调用此操作的代码

# in middleware
#
def call(env)
  env['action_controller.instance'].class.action(:print_name).call(env)
end
这当然会引发
ArgumentError

我不知道如何将参数传递给
action
call。以下是消息来源:

# in action_pack/lib/action_controller/metal.rb
#
def self.action(name, klass = ActionDispatch::Request)
      middleware_stack.build(name.to_s) do |env|
        new.dispatch(name, klass.new(env))
      end
end
如您所见,它从提供的控制器操作返回机架端点。我看我不可能在这里进行辩论

最后,我使用
class\u eval
动态更改了控制器,然后从该代理方法调用控制器方法

# in middleware
#
def define_proxy_method(klass)
      klass.class_eval do
            def call_the_real_method
              print_name(request.env['fake_attribute'])
            end
      end
 end

def call(env)
  define_proxy_method(env['action_controller.instance'].class)
  env['fake_attrbute'] = "Yukihiro"
  env['action_controller.instance'].class.action(:call_the_real_method).call(env)
end

这看起来很脏,我想知道一个更好的方法。谢谢。

你不想在你的行为上争论。中间件应该只与请求环境交互,而不是试图直接调用控制器

您可以在参数散列中传递相同的值:

# middleware
#
def call(env)
  request = Rack::Request.new(env)
  request['name'] = get_name
end
并从控制器中的参数散列中读取:

# my_controller.rb
# 
def print_name
    render :text => "Hello, #{params['name']}!"
end

无论你想做什么,都必须有更好的方法。如果您可以为最终要完成的任务提供更多的上下文,那么可能有一个更简单的解决方案。我正在尝试在抛出异常后重定向到特定的控制器操作。基本上,这是一个为空气制动宝石。很难找到从中间件调用控制器方法的示例。不过,谢谢你的评论。是的,我注意到这样做是错误的。对于rails 2.x,它是这样实现的,因为它在公共(例外)中定义了一个
rescue\u action\u,在
ActionController
中定义了
。我试图在不改变方法调用的情况下为Rails3.x实现相同的行为。谢谢你的回答->接受,投票和赏金:)谢谢。欢迎您在gmail或gchat上通过winfield.peterson向我发送电子邮件,以便进一步讨论。您可能能够将异常处理/报告提取到帮助器类中,并在中间件和控制器中使用它。如果它有控制器特定的重定向逻辑或其他东西,你可以把它放在一个块中?很高兴完成完整解决方案的循环。