Class: RuboCop::Cop::Discourse::Plugins::NoMonkeyPatching

Inherits:
Base
  • Object
show all
Defined in:
lib/rubocop/cop/discourse/plugins/no_monkey_patching.rb

Overview

Don’t monkey-patch classes directly in ‘plugin.rb`. Instead, define additional methods in a dedicated mixin (an ActiveSupport concern for example) and use `prepend` (this allows calling `super` from the mixin).

If you’re just adding new methods to an existing serializer, then use ‘add_to_serializer` instead.

Examples:

generic monkey-patching

# bad
::Topic.class_eval do
  has_many :new_items

  def new_method
  end
end

# good
module MyPlugin::TopicExtension
  extend ActiveSupport::Concern

  prepended do
    has_many :new_items
  end

  def new_method
  end
end

reloadable_patch { ::Topic.prepend(MyPlugin::TopicExtension) }

for serializers

# bad
UserSerializer.class_eval do
  def new_method
    do_processing
  end
end

# good
add_to_serializer(:user, :new_method) { do_processing }

Constant Summary collapse

MSG =
"Don’t reopen existing classes. Instead, create a mixin and use `prepend`."
MSG_CLASS_EVAL =
"Don’t call `class_eval`. Instead, create a mixin and use `prepend`."
MSG_CLASS_EVAL_SERIALIZERS =
"Don’t call `class_eval` on a serializer. If you’re adding new methods, use `add_to_serializer`. Otherwise, create a mixin and use `prepend`."
MSG_SERIALIZERS =
"Don’t reopen serializers. Instead, use `add_to_serializer`."
RESTRICT_ON_SEND =
[:class_eval].freeze

Instance Method Summary collapse

Instance Method Details

#on_class(node) ⇒ Object



74
75
76
77
78
79
80
81
# File 'lib/rubocop/cop/discourse/plugins/no_monkey_patching.rb', line 74

def on_class(node)
  return unless in_plugin_rb_file?
  return unless existing_class?(node)
  if serializer?(node)
    return add_offense(node, message: MSG_SERIALIZERS)
  end
  add_offense(node, message: MSG)
end

#on_send(node) ⇒ Object



67
68
69
70
71
72
# File 'lib/rubocop/cop/discourse/plugins/no_monkey_patching.rb', line 67

def on_send(node)
  if serializer?(node)
    return add_offense(node, message: MSG_CLASS_EVAL_SERIALIZERS)
  end
  add_offense(node, message: MSG_CLASS_EVAL)
end