wechat
wechat copied to clipboard
与rails 5/6存在冲突,不知道是哪一方有问题
rails 5 + jbuilder 2.6 + WeChat 0.8.3, 会导致api json输出body部分为空。具体问题见以下链接https://github.com/rails/jbuilder/issues/346中charleyw的回复。
@charleyw 我的理解是如果使用了jbuilder,还使用了WeChat,会导致jbuilder输出问题?我自己的项目已经用了jbuilder 2.6.1,似乎没有这个问题?测试也无法复现,能给个可复现的例子么?最好是rspec的failure的测试。
昨天用pry-byebug跟踪了一下,发现不是jbuilder的问题,是和rails5有冲突。 在 wechat_responder.rb,中添加
if defined? Base
class << Base
include WechatResponder
end
end
if defined? API
class << API
include WechatResponder
end
end
后,在controller中查看祖先链时,发现少了ActionView::Rendering
,导致了不能render正确的模板。ActionView::Rendering
中有个方法_normalize_options
,用于设置render的模板(jbuilder的模板)。如果缺少了这个模块,就会再往上调用祖先的_normalize_options
,就会导致模板丢失,也就不render了。
=> [Api::V1::HomesController,
#<Module:0x000000061d6d10>,
Api::V1::ApplicationController,
Knock::Authenticable,
#<Module:0x00000006231300>,
#<Module:0x000000064458d0>,
#<Module:0x000000064458f8>,
ActionController::API,
ActionController::ImplicitRender,
ActionController::Helpers,
AbstractController::Helpers,
ActiveRecord::Railties::ControllerRuntime,
ActionDispatch::Routing::RouteSet::MountedHelpers,
ActionController::ParamsWrapper,
ActionController::Instrumentation,
ActionController::Rescue,
ActionController::DataStreaming,
ActionController::ForceSSL,
AbstractController::Callbacks,
ActiveSupport::Callbacks,
ActionController::StrongParameters,
ActiveSupport::Rescuable,
ActionController::BasicImplicitRender,
ActionController::ConditionalGet,
ActionController::Head,
ActionController::Renderers::All,
ActionController::Renderers,
ActionController::Rendering,
ActionController::ApiRendering,
-------就是这个> ActionView::Rendering,
ActionController::Redirecting,
ActiveSupport::Benchmarkable,
AbstractController::Logger,
ActionController::UrlFor,
AbstractController::UrlFor,
ActionDispatch::Routing::UrlFor,
ActionDispatch::Routing::PolymorphicRoutes,
AbstractController::Rendering,
ActionView::ViewPaths,
#<Module:0x00000003381fc8>,
ActionController::Metal,
ActionController::Testing::Functional,
AbstractController::Base,
ActiveSupport::Configurable,
ActiveSupport::ToJsonWithActiveSupportEncoder,
Object,
PP::ObjectMixin,
ActiveSupport::Dependencies::Loadable,
JSON::Ext::Generator::GeneratorMethods::Object,
ActiveSupport::Tryable,
Kernel,
BasicObject]
如果注释掉wechat_responder.rb中的那段代码,ActionView::Rendering
就回来了。
而且发现,只要在wechat_responder.rb中将对上述注释掉的代码改为仅打开API,也会出现同样的问题,比如:
module ActionController
class API
end
end
至于为何会导致ActionView::Rendering
丢失,还在研究。
刚才看了一下,这个问题只有在rails 5的API模式下才能重现。
我也遇到了同樣的問題,但沒有使用你們的 wechat gem。
我是把原本 app 裡面繼承 ActonController::Base
的 api 改成繼承 ActionController::API
從而發現問題。從頭 rails new 一個 app 則沒有這個問題。
我的环境是rails5 API的,也遇到了类似的问题
如果直接在controller里引用wechat_api,启服务时则会提示找不到
undefined local variable or method
wechat_api' for XxxController:Class`
如果把继承换成ActionController::Base则没问题,但是不能那么干:)
看了源码后,有样学样加了这样一段在controller里,就能通过了
module ActionController class << API include WechatResponder end end
那么有两个问题:
-
在wechat_responder.rb中,以下这段代码明显是把include默认加到了ActionController::Base中而不是API,这个是为啥?
if defined? Base class << Base include WechatResponder end elsif defined? API class << API include WechatResponder end end
-
如果我不是把
include
加在ActionController::API中而是直接放到我自己的controller中,则会提示``class:XxxController': uninitialized constant WechatResponder (NameError)`这是为什么?
暂时可以通过手工添加include ActionView::Rendering
来解决这个问题:
class ApplicationController < ActionController::API
include ActionView::Rendering
end
这个问题暂时还没解决,引入 wechat
这个 gem 后,jbuilder 的输出就是空的,引入 include ActionView::Rendering
后,能解决 jbuilder 的问题,但是 render json: {ok: 1}
这种又不能用了。。
个人认为,插件最好不要修改框架底层的东西
wechat (0.8.8)出现同样的问题 会退到wechat (0.8.4)就好了
@mysterytree 能在本地改一下最新0.8.8的这几行确认一下么?
bundle open wechat # edit lib/action_controller/wechat_responder.rb:L66
if defined? Base
class << Base
include WechatResponder
end
elsif defined? API
class << API
include WechatResponder
end
end
能在本地改一下最新0.8.8的这几行确认一下么?
@Eric-Guo 实测0.8.11是无法在rails5 api下正常显示json返回的结果的。在0.8.11下按上面回复的修改后可以正常显示出json返回的结果的
但是修改之后GET访问 /wechat 是会报错的,错误信息为“undefined local variable or method `wechat_responder' for WechatsController:Class”
@numbcoder 找到了一个解决方法,在 Rails 5.1.4 + Jbuilder 2.7.0 + wechat 0.8.12 可以正常使用
class ApplicationController < ActionController::API
include ActionView::Rendering
def render_to_body(options)
_render_to_body_with_renderer(options) || super
end
end
和 @numbcoder 一样,jbuilder 和 render: json 不能同时用
今天我也遇到了,直接include 可解,Rails 6.0.1
class EventsController < ActionController::API
include ActionView::Rendering
# Support render json: nil
def render_to_body(options)
_render_to_body_with_renderer(options) || super
end
end