ruby
为了实现如下效果,写rails的时候不再重复的写路由,今天决定搞一点事
核心代码 app/controllers/concerns/api_defined.rb:
module ApiDefined
extend ActiveSupport::Concern
included do
mattr_accessor :ns, :request_param, :basepath
@@ns = name.deconstantize.split("::").map(&:underscore).join('/')
self.extend ClassMethods
end
module ClassMethods
%w[get post put delete].each do |http_method|
define_method http_method do |method_name, path: nil, param: nil, on_collection: true, on_member: nil, &blk|
on_collection = !on_member unless on_member.nil?
define_method method_name, &blk
path = path || get_path(http_method, method_name, param, on_collection)
$routes << {method: 'get', path: path, action: "#{name.deconstantize.split("::").map(&:underscore).join('/')}/#{controller_name}##{method_name}"}
end
end
def get_path http_method, method_name, param, on_collection
path = basepath || "#{ns}/#{controller_name}"
on_collection = false if param
if http_method == 'get'
if method_name == 'show'
on_collection, method_name = true, nil
elsif method_name == 'index'
method_name = nil
end
elsif http_method == 'put' && method_name == 'update'
on_collection, method_name = true, nil
elsif http_method == 'delete' && method_name == 'destroy'
on_collection, method_name = true, nil
end
path += "/:#{request_param || param.presence || 'id'}" unless on_collection
path += "/#{method_name}" if method_name
path
end
def namespace value
self.ns = value
end
def request_mapping value
self.basepath = value
end
def param value
self.request_param = value
end
end
def valid! param_name, *args, &blk
param! param_name, *args, &blk
self.singleton_class.mattr_accessor param_name
self.send("#{param_name}=", params[param_name])
end
end
在 ApplicationController 中 include ApiDefined
增加 config/initializers/routes.rb
$routes = []
增加一个module,加载controller所有类(用于在开发环境reload代码的时候,重载路由,防止懒加载的问题)
# app/controllers/init.rb
module Pro::V2::Init end
# 注意这里只会加载app/controllers/目录下的controller
# 如果要加载子目录下的,需要替换为app/controllers/*/*,并且要注意module
Dir["#{Rails.root}/app/controllers/*"].each do |filename|
klass_name = File.basename(filename, '.rb').classify
begin
klass_name.constantize
rescue LoadError, NameError
nil
end
end
在 config/application.rb中增加几行代码
config.to_prepare do
$routes = []
Init
Rails.application.reload_routes!
end
发表于 2021.07.01
© 自由转载 - 非商用 - 非衍生 - 保持署名