Created
July 4, 2011 21:55
-
-
Save skilldrick/1063993 to your computer and use it in GitHub Desktop.
Avoiding Demeter violations in Rails
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
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
I had to move the call to
super
to the end ofrespond_to?
becausesuper
may call a callback - seemed safer to leave it at the end (if a bit less efficient).