From: Ryan Leavengood Date: 2006-04-21T01:13:22+09:00 Subject: Re: [SUMMARY] Refactoring (#75) On 4/20/06, Molitor, Stephen L wrote: > > Would you (or > someone else) care to give examples of 'Replace Similar Methods with > Metaprogrammed Definitions' and a 'Convert a Family of Methods to a > Single method_missing()'? I'll provide an example: Let's say you have a class for managing a list of music. Each item in the list is a class which contains a lot of meta-data about the music files (artist, title, album, track number, duration, genre, release date, etc.) Part of managing this list of music is sorting it by various criteria, for display in a media application for example. There are a lot of different ways to sort based on the various kinds of meta-data, and it would be a pain to have to code a special method to sort on each type of meta-data: list.sort_by_artist, list.sort_by_title, etc. Of course in this case it might not be too difficult to just do a custom sort when needed: list.sort_by {|song| song.artist} But why not make things really handy by adding a method missing? # Full test code class Song < Struct.new('Song', :title, :artist, :album) def to_s "#{title} by #{artist} (#{album})" end end class MusicList attr_accessor :list def initialize @list = [] end def method_missing(name, *args) if name.to_s =~ /sort_by_(.*)/ puts "Sorting by #$1:" @list.sort_by {|song| song.send($1.to_sym)} end end end if $0 == __FILE__ music = MusicList.new music.list << Song.new('Here I Am', 'Al Green', 'Greatest Hits') music.list << Song.new('Ain\'t No Sunsine', 'Al Green', 'Greatest Hits') music.list << Song.new('Until It Sleeps', 'Metallica', 'Load') music.list << Song.new('Bleeding Me', 'Metallica', 'Load') music.list << Song.new('King Nothing', 'Metallica', 'Load') music.list << Song.new('Shiver', 'Maroon 5', 'Songs About Jane') music.list << Song.new('This Love', 'Maroon 5', 'Songs About Jane') puts music.sort_by_title, '----' puts music.sort_by_artist, '----' puts music.sort_by_album, '----' end # End test code Now things like list.sort_by_artist and list.sort_by_title will call method missing, and any new meta-data can be sorted by without changing the list code. Ryan