Create config/initializers/reload_api.rb.
if Rails.env.development?
ActiveSupport::Dependencies.explicitly_unloadable_constants << "Twitter::API"
api_files = Dir["#{Rails.root}/app/api/**/*.rb"]
api_reloader = ActiveSupport::FileUpdateChecker.new(api_files) do
Rails.application.reload_routes!
end
ActionDispatch::Callbacks.to_prepare do
api_reloader.execute_if_updated
end
end
这个报错啊!
尝试了 rubychina 的源码,修改之后刷新浏览器也不是每次都起作用……
#2 楼 @lytsingsun 3.2 也是可以的啊,放在 app/api 下本来就是可以的,在 application.rb 中加上
config.autoload_paths += %W(#{config.root}/app/api)
我们的做法是这样的:
config.ru 文件中设置
if Rails.env.production?
map '/api' do
run App.instance
end
end
routes.rb 文件中设置
mount App.instance => '/api' unless Rails.env.production?
App.instance 是一个包装的 rack app,可以加一些 middleware
这样在生产环境下就可以直接到 api,不用走 rails 这一层,在开发环境下走 rails,这样代码也可以自动加载,更新。
#6 楼 @kamechen 按照你的建议我修改了下,uninitialized constant App (NameError)。不知是不是我有什么地方配置的不对. config.ru 文件
# This file is used by Rack-based servers to start the application.
require ::File.expand_path('../config/environment', __FILE__)
run Rongyi::Application
if Rails.env.production?
map '/grape' do
run App.instance
end
end
routes.rb 文件
require 'api'
mount App.instance => '/grape' unless Rails.env.production?
application.rb 文件
config.autoload_paths += %W(#{config.root}/app/grape)
#11 楼 @lytsingsun App 是我们自己定义的一个类,在 app/api 目录下,类似下面这样
class App
def self.instance
@instance ||= Rack::Builder.new do
use Middlewares::Logger, Api.logger
run Api
end.to_app
end
end
这个只是用来加入一些 middleware 的,如果你不需要,你也可以直接吧 App.instance 换成你的 Api
我们 3.2.12 实现了 auto reload,以上说的都是必须步骤 但是楼主可能还有一个地方没有改掉
# config/initializers/reload_api.rb
if Rails.env.development?
ActiveSupport::Dependencies.explicitly_unloadable_constants += [
# 这里列出需要自动reload的类
'V1::OutlineApi','V1::UserApi','V1::FavoriteApi','V1::ArticleApi','V1::CommentApi',
'V1::FriendshipApi', 'V2::FriendshipApi'
]
api_files = Dir["#{Rails.root}/app/api/**/*.rb"]
api_reloader = ActiveSupport::FileUpdateChecker.new(api_files) do
Rails.application.reload_routes!
end
ActionDispatch::Callbacks.to_prepare do
api_reloader.execute_if_updated
end
end
比较笨的办法但是好歹实现了。
#2 楼 @lytsingsun Rails4+ 是可以的,我亲测过。Rails3 不清楚。如果是纯 Rack Server,可以尝试在 config.ru 下面增加如下代码:
if ENV['RACK_ENV'] == "development"
use Rack::Reloader
end
#13 楼 @lytsingsun 不好意思,是我弄错了,我们那个也是在 Rails 4 的版本下做的,Rails 3 下还不支持自动 reload,在 Rails 3 下要解决这个问题,14 楼 @shawnyu 的方法应该可以,17 楼 @Victor 说的 shotgun 也是可以的,只是 shotgun 可能会比较慢
Rails 3.2.14 Grape 0.6.1
刚刚遇到这个问题,实测 autoload 可以搞定
routes.rb
require_dependency 'api_v2/grape' if Rails.env.development?
mount ApiV2::Grape => '/'
application.rb
config.watchable_dirs['api_v2'] = [:rb]
config.autoload_paths << "#{config.root}/api_v2"
#27 楼 @zangcw 实现 rack 应用加载的几种方法:
Reload feature in development environment
run: bundle exec guard #eg. grape-on-rack
[gem shot-gun] https://github.com/rtomayko/shotgun
[gem rerun] https://github.com/alexch/rerun
这个问题,我最近找到真正原因了,需要确保 API 代码存放的目录复合 Rails Autoload 的命名规范。
很多项目 (Ruby China、GitLab)早起的 API 代码在 module 命名,和文件存放的位置上是不规范的,理论上在 autoload_paths 里面加上了 lib/api 以后,就无须手动 require 的,命名符合 Rails 标准,加载会自动执行,同时 reload 的时候能正确清理。
正确的命名(Class、Module 和文件夹命名)以后,你就不会再遇到这样的错误:
Error: A copy of Gitlab::CurrentSettings has been removed from the module tree but is still active
参考: