Home > Announcements > Class, Module and Test Example

Class, Module and Test Example

September 27th, 2009 Jonathan Leave a comment Go to comments

In the Sunday section, we created a small application that several students requested the final source for. It includes examples of:

  • Class inheritance
  • Raising and catching exceptions
  • Using a module via include and extend
  • Testing using Test::Unit
  • Spreading code between multiple files
  • Using method_missing to dynamically add methods
  • How to tune a Ukulele for fun and profit

I tried to make use of as much of the last two lectures as possible. If you have any questions about how this works, or why things are done the way they are, feel free to comment below.
You can click here to downloaded the completed source code.

Run “ruby section.rb” to actually run the application. Edit this file as you see fit.

Run “ruby instrument_test.rb” to run the tests.

Categories: Announcements Tags:
  1. Ron Newman
    September 28th, 2009 at 12:54 | #1

    When running this application or tests, what code path will cause method_missing to be invoked?

  2. Ron Newman
    September 28th, 2009 at 13:37 | #2

    (Also, when and where is this Sunday section? I thought it had been cancelled for lack of interest)

  3. September 28th, 2009 at 14:12 | #3

    @Ron Newman

    This is Jonathan's regular Sunday section -- not the one which I offered to hold, which interested no one.

  4. Jonathan
    September 28th, 2009 at 14:19 | #4

    The Sunday section is remote only. It's at 4:30 EST.

    If you'd like to attend, simply email me (jbarket [at] sleepunit.com) and I'll make sure to send you the URL. If there is a significant interest in coming to my section, I'll make a habit of posting the URL on the blog.

    Since that code is the end result of what we played around with in section, method_missing never actually gets called. We ran through it, but I removed it. You can easily add code back to section.rb to play with it.

    Essentially, you can call string_tuning_N where N is the string number you're looking for. method_missing will dynamically catch all of those and then call string_tuning(N). string_tuning returns the tuned value from strings[]. Since tuning is done from top to bottom (G, C, E, A) but strings are numbered bottom to top (4, 3, 2, 1), string_tuning reverses the array, and then subtracts one so that string 1 corresponds to array index 0.

    We didn't get a chance to write any tests for method_missing, but that's a good idea for a place to test. Similar to how num_strings is tested to verify that it is returning the correct number of strings based on what self.tuning is set to, you could make calls to methods you expect to exist based on your tuning... string_tuning_1, string_tuning_2 and so on... or you could go beyond that and call something that _shouldn't_ exist (string_tuning_5 for the Ukulele class) and verify that you're correctly handling the case when they're stepped outside of the proper range.

  5. Ron Newman
    September 28th, 2009 at 14:34 | #5
    irb -r instrument.rb
    irb(main):001:0> g = Guitar.new
    => #<Guitar:0x3df884 @tuning=["E", "A", "D", "G", "B", "E"], @tuning_hint="Eddie Ate Dynamite, Good Bye Eddie", @strings=[], @player="Jonathan Barket">
    
    irb(main):002:0> g.tune_strings
    => ["E", "B", "G", "D", "A", "E"]
    
    irb(main):003:0> g.string_tuning_2
    NoMethodError: undefined method `string_tuning_2' for #<Guitar:0x3df884>
    	from /Users/ronnewman/cs168/instrument/stringed.rb:49:in `method_missing'
    	from (irb):3
    	from /Users/ronnewman/.ruby_versions/ruby-1.9.1-p243/bin/irb:12:in `<main>'
    

    I think your Stringed#method_missing is always calling super, so no matter what argument it is called with, it's going to fail.

  6. Jonathan
    September 28th, 2009 at 15:06 | #6

    You're right. stringed.rb should be changed to the following:


    def method_missing(m, *args)
    # catch all methods beginning with "string_tuning_"
    # this allows us to support an infinite number of strings, rather than simply 1..9
    if m.to_s[0..13] == "string_tuning_"
    # call string_tuning with everything that comes after string_tuning_
    # so string_tuning_10 calls string_tuning(10)
    string_tuning(m.to_s.delete('string_tuning_'))
    else
    super
    end
    end

  7. Ron Newman
    September 28th, 2009 at 16:03 | #7

    Much better now, thanks.

  8. peter
    September 29th, 2009 at 21:15 | #8

    All -

    Now I'm starting to play with Rails, I had a slight issue with starting the WEBrick server on Ubuntu. I am running with the original spec setup in Assignment 0. I built it all from source, which went fine. Except when I started the WEBrick it spit out some openssl lib errors. A little googling solved the problem.

    Thought Id post a link or 2, in case anyone had the same error.

    I already had the openssl libssl-dev packages this guy said:
    http://linuxnuggetz.blogspot.com/2009/06/ruby-on-rail-on-ubuntu.html

    But it was this particular comment that solved my issue as well. It involves rebuilding a piece of ruby from source, assuming thats how you installed it as well.
    http://www.ruby-forum.com/topic/136893#609118

    HTH

    -peter

  9. September 29th, 2009 at 21:31 | #9

    @peter

    Thanks. I sent an e-mail to all Linux students to warn them of this problem.

    Just curious, Peter: Did you use the ruby_switcher.sh script for your setup . . . ?

  10. peter
    September 29th, 2009 at 21:47 | #10

    @john

    No I didnt. I'm using Ubuntu 9.04 and just went right down the list as it was on the site. Installed ruby, rubygems from source, downloaded the actual .gem file for rails, used apt to get sqlite3, got the .gem for sqlite3-ruby

    * Ruby 1.9.1p243
    * RubyGems 1.3.5
    * Ruby on Rails 2.3.3 only
    * Sqlite 3.4.0 or later
    * The sqlite3-ruby gem, version 1.2.5

    But that script does look pretty handy!

    I did it the old fashioned way and installed ruby to /usr/local/ruby-1.9.1p243/ and then symlinked that to /usr/local/ruby/. An old trick of mine, so if I did need to switch, I could install another version and just change the symlink.

    -peter

  1. No trackbacks yet.