添加jsonapi-suite后出现未初始化常量错误,如何启用ActiveRecord适配器?
在现有Rails 5.2.0项目中添加jsonapi-suite相关Gem后,执行$ curl localhost:3001/groups返回如下错误:
ActionController::RoutingError (uninitialized constant JsonapiCompliable::Adapters::ActiveRecord): app/resources/application_resource.rb:9:in `<class:ApplicationResource>' app/resources/application_resource.rb:5:in `<main>' app/resources/group_resource.rb:1:in `<main>' app/controllers/groups_controller.rb:3:in `<class:GroupsController>' app/controllers/groups_controller.rb:1:in `<main>'
项目相关配置代码
Gemfile
gem 'jsonapi_suite', '~> 0.7' gem 'jsonapi-rails', '~> 0.3.0' gem 'jsonapi_swagger_helpers', '~> 0.6', require: false gem 'jsonapi_spec_helpers', '~> 0.4', require: false gem 'kaminari', '~> 1.0'
ApplicationController
class ApplicationController < ActionController::API + # Bootstrap jsonapi_suite with relevant modules + include JsonapiSuite::ControllerMixin + + register_exception JsonapiCompliable::Errors::RecordNotFound, + status: 404 + + # Catch all exceptions and render a JSONAPI-compliable error payload + # For additional documentation, see https://jsonapi-suite.github.io/jsonapi_errorable + rescue_from Exception do |e| + handle_exception(e) + end +
GroupsController
class GroupsController < ApplicationController jsonapi resource: GroupResource strong_resource :group before_action :apply_strong_params, only: [:create, :update] def index groups = Group.all render_jsonapi(groups) end def show scope = jsonapi_scope(Group.where(id: params[:id])) instance = scope.resolve.first raise JsonapiCompliable::Errors::RecordNotFound unless instance render_jsonapi(instance, scope: false) end def create group, success = jsonapi_create.to_a if success render_jsonapi(group, scope: false) else render_errors_for(group) end end def update group, success = jsonapi_update.to_a if success render_jsonapi(group, scope: false) else render_errors_for(group) end end def destroy group, success = jsonapi_destroy.to_a if success render json: { meta: {} } else render_errors_for(group) end end end
app/resources/group_resource.rb
class GroupResource < ApplicationResource type :groups end
控制台调试结果
[4] pry(main)> JsonapiCompliable::Adapters => JsonapiCompliable::Adapters [5] pry(main)> JsonapiCompliable::Adapters::ActiveRecord NameError: uninitialized constant JsonapiCompliable::Adapters::ActiveRecord
app/resources/application_resource.rb
class ApplicationResource < JsonapiCompliable::Resource use_adapter JsonapiCompliable::Adapters::ActiveRecord end
请问为何JsonapiCompliable::Adapters::ActiveRecord不可用,如何使其可用?
原因分析
这个错误的核心问题很明确:jsonapi_compliable的ActiveRecord适配器没有被加载。从jsonapi_suite 0.7版本开始,官方把不同ORM的适配器拆成了独立的Gem包,默认不会自动引入ActiveRecord适配器,所以你的代码找不到这个常量。
解决办法
1. 补充ActiveRecord适配器Gem
打开你的Gemfile,添加专门的ActiveRecord适配器Gem(版本号建议和jsonapi_suite保持一致,避免兼容性问题):
gem 'jsonapi_compliable-active_record', '~> 0.7'
2. 安装并重启服务
执行bundle命令安装新Gem:
bundle install
然后必须重启你的Rails服务器——新Gem只有在服务器重启后才会被加载生效。
3. 验证修复效果
重启后打开rails控制台,再次尝试调用这个常量:
[1] pry(main)> JsonapiCompliable::Adapters::ActiveRecord
如果返回JsonapiCompliable::Adapters::ActiveRecord而不是报错,说明问题已经解决。此时再请求localhost:3001/groups应该就能正常返回数据了。
备选方案(不推荐)
如果你不想添加额外的Gem,可以手动在代码里require适配器文件。比如在app/resources/application_resource.rb开头加上:
require 'jsonapi_compliable/adapters/active_record'
不过这种方式不推荐,因为后续版本更新可能会改变文件路径,导致代码出错,还是用官方提供的独立Gem更稳妥。
内容的提问来源于stack exchange,提问作者martins

