ruby-on-rails - 使用 Rack 中间件的参数调用 Controller 操作

标签 ruby-on-rails ruby rack

有没有一种方法可以将参数传递给来自中间件的 Controller 操作调用?

这是 Controller 代码中的 Action

# 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 调用。这是来源:

# 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

如您所见,它从提供的 Controller 操作返回 Rack 端点。我看不出我可以在这里提出争论。

我最终使用 class_eval 动态更改 Controller ,然后从该代理方法调用 Controller 方法。

# 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

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

最佳答案

你不想对你的行动提出论据。中间件应该只与请求环境交互,而不是尝试直接调用 Controller 。

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

# middleware
#
def call(env)
  request = Rack::Request.new(env)
  request['name'] = get_name
end

并从 Controller 中的参数散列中读取:

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

关于ruby-on-rails - 使用 Rack 中间件的参数调用 Controller 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10072734/

相关文章:

ruby-on-rails - 如何在 ruby​​ on rails 中将数据表从管理命名空间访问到公共(public)

ruby-on-rails - 如果我使用begin…rescue并发生错误,还会发生回滚吗?

ruby - Elasticsearch - 无法使用建议字段进行搜索 ("is not a completion suggest field")

ruby - 为什么这些方法没有解决?

ruby 哈希 : getting a set of keys from sorted values

ruby - 将参数传递给新的 sinatra 应用程序

ruby - Sinatra 发布请求时出现无效的 URI 错误

ruby - 壳外薄

ruby-on-rails - Sidekiq计划的作业会自动删除(Sidekiq + Rails)

ruby-on-rails - 将日期字符串转换为时区特定格式