问题描述
我正在尝试找到一种方法来覆盖Rails gem actionpack/http/parameters.rb
中的变量。我必须处理ndjson流,并且Rails中间件无法处理ndjson
。它使用ActiveSupport::JSON.decode
DEFAULT_PARSERS = {
Mime[:json].symbol => -> (raw_post) {
data = ActiveSupport::JSON.decode(raw_post)
data.is_a?(Hash) ? data : { _json: data }
}
}
当它尝试解析ndjson时出现此错误
Actiondispatch::Http::Parameters::ParseError in MyController#activity
我的目标是重写解析器,使其能够解码ndjson ...可能使用split(\n)
而不是当前的ActiveSupport::JSON.decode
。
到目前为止,我已经尝试在lib/
文件夹中创建一个文件并使用以下代码,但是它似乎并没有进行覆盖。我如何在没有猴子补丁的情况下做到这一点
require 'lib/action_dispatch/http/parameters'
module MyParser
module Overrides
extend ActiveSupport::Concern
DEFAULT_PARSERS = {
Mime[:json].symbol => -> (raw_post) {
data = raw_post.split("\n")
data = ActiveSupport::JSON.decode(data)
data.is_a?(Hash) ? data : { _json: data }
}
}
end
end
Actiondispatch::Http::Parameters.include(MyParser::Overrides)
更新:
我尝试的第二种方法:
Actiondispatch::Http::Parameters.const_set(:DEFAULT_PARSERS,{
Mime[:json].symbol => -> (raw_post) {
data = raw_post.split("\n")
data = ActiveSupport::JSON.decode(data)
data.is_a?(Hash) ? data : { _json: data }
},})
不幸的是,它不断警告我常量已被定义。
解决方法
我采取了另一种方法。我没有重新初始化常量,而是在config/initializers/custom_params.rb
中创建了一个文件来覆盖使用parse_formatted_parameters
变量的方法DEFAULT_PARSERS
(here)。在内部,我能够更改json
数据类型的Proc值。
这方便地重写了该方法,并允许ActionDispatch::Http::Parameters
模块将ndjson
传递给我的控制器而没有任何解析错误。
module ActionDispatch
module Http
module Parameters
extend ActiveSupport::Concern
private
def parse_formatted_parameters(parsers)
parsers[Mime[:json].symbol] = Proc.new { |raw_post|
data = ActiveSupport::JSON.decode(raw_post) rescue nil
if !data
data = raw_post
end
data.is_a?(Hash) ? data : { _json: data }
}
return yield if content_length.zero? || content_mime_type.nil?
# rubocop:enable all
strategy = parsers.fetch(content_mime_type.symbol) { return yield }
begin
strategy.call(raw_post)
rescue # JSON or Ruby code block errors.
my_logger = logger || ActiveSupport::Logger.new($stderr)
my_logger.debug "Error occurred while parsing request parameters.\nContents:\n\n#{raw_post}"
raise ParseError
end
end
end
end
end