Rails action 动态调用

March 27, 2013 21:27


前两天在一个问题上纠结了好久,恩,一个全是API的项目B,要通过项目A才能调用到项目B的API。 本来是想全类似代理一样的过去,但考虑到不丗的API在项目A中的扩展,控制问题,不得不放弃此方法了。

我就写了一个通配的路由所有到B项目的API全走这个action,然后让此action来处理是走扩展的action, 还是自动直接去如代理一般的去请求,代码思路如下:

# routes.rb
# :yy 为了与本地API区别开来
# 所有的请求都到yy的base_action里面去
match "/api/:yy/*b_path" => "api/yy#base_action"
# Controller 1
class Api::YyController < Api::BaseController
  def base_action
    local_controller, action = params[:b_path].to_local_controller
    if local_controller && local_controller.has_action(action)
      # call local_controller#action
    else
      http_req("project B", api_params)
    end
  end
end

# Controller 2
class Api::Yy::XxController < Api::YyController
  def list
  end
end

如上面的代码,/api/yy/xx/show, 就会走"httpreq("project B", apiparams)"

而 /api/yy/xx/list, 由于有了Api::Yy::XxController,而且这个Controller中有list这个action, 所有直接交给api/yy/xx#list来处理

然后就是我纠结的问题了,怎么交给list处理?,以前想过写个模块直接extend当前controller实例中来, 但这样list就没有控制器的功能了,如filter,cache等等,然后就是想着跳转,但redirect_to要路由啊, 然后我想着自动生成路由,太痛苦了。。

然后我用了一个变态的方法,new出list的controller,然后把当前controller的实例变量复制过去, 然后调用list,再然后把实例变量复制回来,好变态的方法,而且controller的功能也失去了。。

最后同事出主意,再写一个通配路由,到api/yy/xx#list,然后跳转,感觉有点蛋疼了, 然后又是中间件,应该说中间件是比较好的一种方法了,不用进action就直接在外面指定好了, 恩这个我也没试过,因为我已经写了一点Controller的代码了,懒的复制再改了,时间有点紧

不信邪的把rails的routes再看了一次,发现了XxController.action(:list)能得到一个rack代码, 然后我直接Api::Yy::XxController.action(:list).call(env),再把response拿到当前controller, 然后设置下response_body这样render不会再运行了,然后 OK。。。

Comments: