Onze dagmethode #18: NilClass#method_missing
Geplaatst door Remco van 't Veer vr, 29 feb 2008 07:25:00 GMT
Waarschuwing: alleen gebruiken onder toezicht van een meerderjarige!
We kennen de whiny nil, zoals toegepast in Rails, maar wat nou whiny?! Bij deze de obedient nil:
class NilClass
def method_missing(*args)
nil
end
end
Geen geklooi meer:
person && person.name && person.name.upcase
Niet echt DRY! Nu met de obedient nil:
person.name.upcase
Het is alweer de laatste dag methode. Ode aan Michiel voor de hoeveelheid gave trucs die hij uit z’n hoge hoed heeft kunnen trekken!

Safe dereferencing… cool!
In Groovy kun je dit gedrag sturen door een vraagteken voor de . te plakken:
eigenlijk vind ik dat mooier dan dit globaal doen.
Ik heb even zitten denken of ik zoiets ook in Ruby zou kunnen maken, maar iets moois krijgt ik niet bedacht… iemand een idee?
Werkt dat ook als person.name nil is?
Het truukje van vandaag is qua functionaliteit een verbetering. Wanneer wil je nou een NoMethodError? Dit is veel nuttiger. Maar aangezien het alle errors opslokt werkt het alleen als je een perfecte programmeur bent die nooit fouten maakt. Ik houd het dus op de whiny nil.
Ik heb trouwens al eens een artikel over iets dergelijks geschreven. De lopende band
Je kunt dan het volgende zeggen:
free(maybe(roman).schrijver.adres.postcode.to_coordinates). Maar de syntax is te onhandig.Werkt dat ook als person.name nil is?
Eeuhmm… natuurlijk… maar dan moet je daar wel ook safe de-referencen als je dat wilt:
Artikel aangepast:
Anders krijg je bij
person?.name.upcasetoch alsnog een NPE als person nil is?ParseTree gebruikt dit ook in een oudere versie, maar Ryan Davis heeft het eruit gesloopt omdat te veel mensen liepen te klagen. Het geeft idd leuke problemen als je het niets vermoedend in je Rails project include.
@p3tor: misschien zoiets?
class NilClass def method_missing_with_safe_dereferencing(*args) nil end def self.with_safe_dereferencing alias_method :old_method_missing, :method_missing alias_method :method_missing, :method_missing_with_safe_dereferencing yield alias_method :method_missing, :old_method_missing end end NilClass.with_safe_dereferencing do person = nil p person.name.upcase end begin person = nil person.name.upcase rescue NoMethodError => e p e.message endOeps… je hebt natuurlijk helemaal gelijk. In mijn eerste voorbeeld werd upcase aangeroepen op null en dat kan natuurlijk niet.
Dit kan allemaal wel:
class Person{ def name = "peter" def nilname = null } p = new Person(); assert "PETER" == p.name.toUpperCase() assert null == p.nilname assert null == p.nilname?.toUpperCase() p = null assert null == p?.name?.toUpperCase()Maar goed, het was een Ruby weblog… ;)
Ai, wat volgorde problemen… tja die oplossing met dat block… zet dan gewoon
Dan wordt het:
Geen slechte notatie, hoewel een
method_missingoplossing een stuk sneller is op MRI en waarschijnlijk ook Rubinius, JRuby e.a.http://ozmm.org/posts/try.html
person.try(:name).try(:upcase)Dank voor alle dagmethodes! Goede serie met leuke ideeën.
Wat een reacties opeens. Maar ik heb nog niks gezien (of bedacht) dat beter is dan
person && (pname = person.name) && pname.upcaseMaar voor de volledigheid (in Haml):
Tada! Geen null pointer problemen ;-)