Skip to content

Instantly share code, notes, and snippets.

@skilldrick
Created July 4, 2011 21:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skilldrick/1063993 to your computer and use it in GitHub Desktop.
Save skilldrick/1063993 to your computer and use it in GitHub Desktop.
Avoiding Demeter violations in Rails
class Example < ActiveRecord::Base
# The rest of the class .....
def get_object_and_method method_name
assoc_methods = [
:push,
:concat,
:build,
:create,
:create!,
:size,
:length,
:count,
:sum,
:empty?,
:clear,
:delete,
:delete_all,
:destroy_all,
:find,
:find_first,
:exists?,
:uniq,
:reset
]
method_string = method_name.to_s
#Iterate over association method names
assoc_methods.map(&:to_s).each do |assoc_method|
#if the missing method starts with the association method
if method_string.starts_with? assoc_method
assoc = method_string.sub(assoc_method, '').sub('_', '')
#and this object responds to the name of the remainder
#of the string or its pluralized form
if self.respond_to? assoc
#then return the object and method names
return [assoc, assoc_method]
elsif self.respond_to? assoc.pluralize
return [assoc.pluralize, assoc_method]
end
end
end
[nil, nil]
end
def method_missing method_name, *args, &block
other_object, other_method = get_object_and_method(method_name)
#if a valid object and method name was derived
if other_object && other_method
#then delegate
send(other_object).send(other_method, *args, &block)
else
super
end
end
def respond_to? method_name, include_private=false
other_object, other_method = get_object_and_method(method_name)
if other_object && other_method
true
else
super
end
end
end
@skilldrick
Copy link
Author

I had to move the call to super to the end of respond_to? because super may call a callback - seemed safer to leave it at the end (if a bit less efficient).

@skilldrick
Copy link
Author

Description: Convert calls of the form model.association.find to model.find_association.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment