class RemoteResource::AttributeMethodAttacher
Public: Creates an instance of the AttributeMethodAttacher
, which is responsible for setting up and attaching methods onto a target class which are used to lookup cached attributes.
Attributes
Public Class Methods
Public: Creates an instance of the AttributeMethodAttacher
, which is responsible for setting up and attaching methods onto a target class which are used to lookup cached attributes.
base_class - the class which will have methods attached to. options - options hash with the following keys (default: {}). Generally,
prefix should be used when overriding the names of all the methods is desired and attributes_map should be used when overriding only a few method names is desired. :prefix - prefix for the names of the newly created methods. :attributes_map - a hash for overriding method names to create. The keys in this hash represent an attribute defined on the base_class. The values are the overriding name of the method to be defined on the target_class.
Returns a new instance.
# File lib/remote_resource/attribute_method_attacher.rb, line 27 def initialize(base_class, options = {}) @base_class = base_class @options = ensure_options(options) end
Public Instance Methods
Public: Set the base_classes’ attribute methods on the given target class. Sets a MethodResolver instance on the target_class as well. Logs warnings if any methods on the target class are overwritten.
target_class - The class upon which the base_classes’ attribute methods
should be set.
path_to_attrs - A string representing a line of ruby code that will be
evaluated. This line is the relative path from a target_class instance to the object that holds the attributes and where the `get_attribute` is defined. If path_to_attrs is (default: self), that implies that this is defining methods on the Base class, because that object contains the `get_attribute` method.
Returns the target_class
# File lib/remote_resource/attribute_method_attacher.rb, line 47 def attach_to(target_class, path_to_attrs = 'self') overwrite_method_warnings(target_class) unless path_to_attrs == 'self' target_class.send(:include, make_attribute_methods_module(path_to_attrs)) end
Private Instance Methods
Internal: Create a basic 1 to 1 (key to value) Hash map of the attribute names. This is intended to be overridden by the attributes_map argument.
# File lib/remote_resource/attribute_method_attacher.rb, line 88 def default_attributes_map {}.tap do |attr_map| @base_class.attributes.keys.each do |method| attr_map[method.to_sym] = method.to_sym end end end
Internal: Populate the attributes map. If no attributes_map arg is given, then attributes_map is a 1 to 1 map (the default_attributes_map
below).
# File lib/remote_resource/attribute_method_attacher.rb, line 80 def ensure_options(options) options[:attributes_map] = default_attributes_map .merge(options[:attributes_map] || {}) options end
Internal: Returns a module with the base_classes’ attributes defined as getter and setter methods.
# File lib/remote_resource/attribute_method_attacher.rb, line 56 def make_attribute_methods_module(path_to_attrs) attribute_methods_module = AttributeMethods.new { extend Mutex_m } attribute_methods_module.synchronize do @base_class.attributes.keys.each do |attributes_method| method_name = @options[:attributes_map][attributes_method] method_name = "#{@options[:prefix]}_#{method_name}" if @options[:prefix] attribute_methods_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{method_name} #{path_to_attrs}.get_attribute(:#{attributes_method}) end def #{method_name}=(other) fail ApiReadOnlyMethod.new('#{method_name}') end RUBY end end attribute_methods_module.freeze attribute_methods_module end
Internal: Log warning methods when this attacher will overwrite methods on the target class.
# File lib/remote_resource/attribute_method_attacher.rb, line 98 def overwrite_method_warnings(target_class) @options[:attributes_map].values.each do |method| method = "#{@options[:prefix]}_#{method}" if @options[:prefix] if present_and_future_public_methods(target_class).include? method log_msg = "#{@base_class.name} is overwriting the " log_msg += "#{method} method on #{target_class.name}" RemoteResource.logger.warn log_msg end end end
Internal: ActiveRecord objects do not define a model’s column methods until the instance is created. In this context, we have the class, so we lookup the ‘future methods’ on the ‘column_names` class method.
# File lib/remote_resource/attribute_method_attacher.rb, line 112 def present_and_future_public_methods(target_class) conflicts = target_class.public_instance_methods if target_class.respond_to? :column_names conflicts += target_class.column_names.map(&:to_sym) end conflicts end