[SUMMARY] Refactoring (#75)

Very sweet, thanks! I'm catching on now. These examples really help.

Steve

···

-----Original Message-----
From: Ryan Leavengood [mailto:leavengood@gmail.com]
Sent: Thursday, April 20, 2006 11:13 AM
To: ruby-talk ML
Subject: Re: [SUMMARY] Refactoring (#75)

On 4/20/06, Molitor, Stephen L <Stephen.L.Molitor@erac.com> 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