Ваш второй monkeypatch работает, так как вы снова открываете класс Symbol.
Первый - нет, потому что все, что делает включение, это добавляет модуль в список включенных модулей. Они вызываются, только если сам класс не определяет конкретный метод или этот метод вызывает super. Таким образом, ваш код никогда не вызывается.
Если вы хотите использовать модуль, вы должны использовать обратный вызов included
:
module CamelcasedJsonSymbol
def self.included(base)
base.class_eval do
alias_method_chain :to_s, :camelcase_json
end
end
def to_s_with_camelcase_json(*args)
to_s_without_camelcase_json(*args).extend(CamelcasedJsonString)
end
end
Я использовал active_record alias_method_chain
, что вы всегда должны делать при исправлении обезьян. Он побуждает вас использовать правильные имена и, таким образом, избегать коллизий.
Это был технический ответ.
При более прагматичном подходе вы должны переосмыслить это. Неоднократное расширение строк, как это нехорошо, приведет к значительному снижению производительности в большинстве реализаций (например, очищает весь кэш методов в MRI) и вызывает сильный запах кода.
Я не знаю достаточно о проблеме, чтобы быть уверенным, или предложить другие решения (может быть, класс Делегат может быть правильным, чтобы вернуться?), Но я чувствую, что это не правильный способ достичь ваших целей .
Поскольку вы хотите преобразовать ключи хэша, вы можете передать параметр в #to_json
и monkeypatch вместо #to_s
, например:
{ :chunky_bacon => "good" }.to_json(:camelize => true)
Моей первой идеей было создать monkeypatch Symbol#to_json
, но это не сработает, как вы указали, поскольку Hash принудительно заставит ключи к строкам перед вызовом to_json, потому что ключи javascript должны быть строками. Таким образом, вы можете вместо этого использовать Hash:
module CamelizeKeys
def self.included(base)
base.class_eval do
alias_method_chain :to_json, :camelize_option
end
end
def to_json_with_camelize_option(*args)
if args.empty? || !args.first[:camelize]
to_json_without_camelize_option(*args)
else
pairs = map do |key, value|
"#{key.to_s.camelize.to_json(*args)}: #{value.to_json(*args)}"
end
"{" << pairs.join(",\n") << "}"
end
end
end