This is good because it reduces duplication.
There is no meaningful performance penalty in defining attribute methods, since it only happens once. There is also no reason *not* to define them, since they get thrown in an included module, so they will not 'overwrite' anything. In fact, this is desirable, since it allows us to call super.
We can just use method_defined? and private_method_defined?
This shouldn't ever happen unless people are doing something particularly weird, but adding a deprecation in case there are bugs not caught by our tests.
Check respond_to_without_attributes? in method_missing. If there is any method that responds (even private), let super handle it and raise NoMethodError if necessary.
This fixes a situation I encountered where a subclass would cache the name of a generated attribute method in @_defined_class_methods. Then, when the superclass has it's attribute methods undefined, the subclass would always have to dispatch through method_missing, because the presence of the attribute in @_defined_class_methods would mean that it is never generated again, even if undefine_attribute_methods is called on the subclass. There various other confusing edge cases like this. STI classes share columns, so let's just keep all the attribute method generation state isolated to the base class.
Make sure we don't redefine an already-defined attribute method.