Gray Soft

The programming blog of James Edward Gray II (JEG2).
  • 4

    DEC
    2006

    Hacking the Gateway

    [Update: The Ruby Gateway was retired in June of 2011. Our community simply grew past the point were we needed to combine the various groups, in my opinion.]

    Though I rewrote the current Gateway and I handle the maintenance, it really belongs to the Ruby community. Because of that, I'm going to release the two primary source files on this blog for all to view and critique. This may have value to those who want to know how the Gateway works, those who would like to implement similar technologies, and those who would like to purpose changes to the Gateway code.

    I do welcome purposed changes to the Gateway, but let's set some ground rules for the right way to make suggestions:

    • I will show the important elements of the Gateway code and do my best to explain it as I go. In return, please take the time to read what I write about the code and try to understand how it works. Poorly developed change requests increase my maintenance time with the Gateway, which all comes out of my free time, so please be considerate.
    • You purpose changes to the Gateway by commenting on the code articles. This is intended to be a public discussion with all of us working together. Don't email me or Ruby Talk ideas, I'm monitoring the comments here.
    • Show code in your requests. I don't want to throw the Gateway in a publicly accessible Subversion repository and start taking patches for several reasons. If you want a change, convince me to implement it. The best way to do that is to throw around some code showing me how we would build your request and how it would make the Gateway better.
    • I am thinking about some elements of the Gateway you are not, like the fact that I run this code on a server provided by my work where security is a consideration and the level of maintenance a change will inflict on me. I ask only that you keep this in mind as we debate changes. In return, I will be as open minded to improvements as possible.
    • Gateway changes will not happen overnight. (See note about free time above.) Please be patient.
  • 1

    DEC
    2006

    What is the Ruby Talk Gateway?

    [Update: The Ruby Gateway was retired in June of 2011. Our community simply grew past the point were we needed to combine the various groups, in my opinion.]

    The Ruby community makes use of both email and Usenet communication, in addition to other resources. The primary mailing list is Ruby Talk and the primary Usenet group is comp.lang.ruby. These two services are joined by the Ruby Gateway.

    In 2001 The Pragmatic Programmers wrote the initial version of the Ruby Gateway to ferry messages back and forth between these two resources. Emails sent to Ruby Talk are posted as Usenet messages and Usenet posts are forwarded to Ruby Talk by the Gateway. The Gateway has had a few guardians and code changes since then, but the functionality remains the same.

    I'm am the current caretaker of the Ruby Gateway. Highgroove Studios generously provides hosting for it and I monitor the system for problems. I also wrote the current version of the Gateway.

    You are free to report Gateway problems for me to look into. Before you do though, please read the following notes:

    Read more…

  • 7

    NOV
    2006

    Doing It All!

    I'm not really in the habit of putting non-code content on this blog, but more than one person asked me the same question at RubyConf. If people really want to know, I'll try to answer. Paraphrasing, the question was:

    How do you keep up with so many Ruby projects?

    First, this question surprised me. Do I really do that much? If you just said yes to that, I would like to introduce you to Ryan Davis. He easily doubles my output and his projects are wicked complex compared to mine.

    That doesn't answer the question though.

    In short, I do as much as I possibly can with the time I have. The truth is that I would like to do a lot more. I turn down at least as many damn cool Ruby projects as I accept because I'm a wimp and not willing to give up my sleep. There are so many crazy cool Ruby projects out there that I would love to be a part of. There just aren't enough hours in the day.

    I guess I still didn't answer the question.

    The question was "How…" and the answer to that is actually trivial. Masayoshi Takahashi summed it up with a single slide in his presentation at RubyConf:

    Read more…

    In: Non-code | Tags: Process | 0 Comments
  • 1

    OCT
    2006

    I Just Want One Character!

    Every so often a person asks the question on Ruby Talk, "How can I get just one character from the keyboard (without needing the user to hit return)?" Everyone is always quick to post solutions, but sadly there are some issues with almost every one of them.

    The general consensus is that this is a tough problem to solve correctly. I say that's the exact reason to let HighLine handle this for you:

    #!/usr/bin/env ruby -w
    
    require "highline/system_extensions"
    include HighLine::SystemExtensions
    
    print "Enter one character:  "
    char = get_character
    puts char.chr
    

    That doesn't look too tough, does it?

    What's terrific about this solution is that under-the-hood HighLine will check your platform and libraries and then try to use the solution that makes the most sense for your environment. The code is really pretty robust too, because people a lot smarter than me have been sending in patches for over a year, slowly eliminating all of those tricky edge cases.

    As you can see, I've split this functionality of HighLine into a separate module so you don't even need to load the full HighLine system. This was done just because this is such a real and common problem. This section of HighLine is one pure Ruby file, so feel free to vendor it if the external dependency is an issue.

    Read more…

  • 2

    AUG
    2006

    RegexpChallenge

    Just recently I have been working with two different people to improve their regular expression skills. To help me in this endeavor, I built a trivial little script we have been using in IRb. To get started, you construct a new challenge object and add a couple of challenges:

    >> reg_chal = RegexpChallenge.new
    No challenges.
    => 
    >> reg_chal.challenge("Gray, James", "James", "The names can vary.")
    => nil
    >> reg_chal.challenge("abbbbbbbc bc", 10)
    => nil
    >> reg_chal.challenge( "    \n\t  ", nil,
    ?>                     "We want to test for non-space data." )
    => nil
    >> reg_chal.challenge( "cogs 9, widgets 12, ...", "12",
    ?>                     "The numbers can vary." )
    => nil
    >> reg_chal.challenge( "I'm a simple sentence, with words.",
    ?>                     %w[I'm a simple sentence with words] )
    => nil
    

    You can ask for challenges to see what you would like to solve:

    >> reg_chal.challenges
    Challenge #0:
       Input:  "Gray, James"
      Output:  "James"
        Note:  "The names can vary."
    Challenge #1:
       Input:  "abbbbbbbc bc"
      Output:  10
    Challenge #2:
       Input:  "    \n\t  "
      Output:  nil
        Note:  "We want to test for non-space data."
    Challenge #3:
       Input:  "cogs 9, widgets 12, ..."
      Output:  "12"
        Note:  "The numbers can vary."
    Challenge #4:
       Input:  "I'm a simple sentence, with words."
      Output:  ["I'm", "a", "simple", "sentence", "with", "words"]
    => nil
    

    Read more…

  • 30

    JUL
    2006

    PStore Meets YAML

    I love the PStore standard library. It's a very graceful interface to get some fairly robust serialized mini-database handling in just a few lines. With it you get:

    1. Transactions with commit and rollbacks (automatic on exception).
    2. File locking, shared and exclusive.
    3. Multiprocessing safety.

    PStore does even more, including some file mode checking and MD5 hashing to avoid unneeded writes, but the above are the major selling points for me.

    Now, if I had to level any one complaint at PStore, it would be that because it uses Marshal under the hood it doesn't create files you can easily browse or tweak by hand. (Marshal is a feature, don't get me wrong. It's fast, which is very helpful.) Sometimes though I want PStore protection with the YAML file format.

    I'm embarrassed to admit that I use to use a hack for this:

    require "pstore"
    require "yaml"
    class PStore; Marshal = YAML; end
    

    That just redefines the Marshal constant in a scope that should only alter PStore. The library only uses dump() and load() and those methods work the same with Marshal and YAML.

    Read more…

  • 29

    JUL
    2006

    YARV Looking Promising, James's C is Not

    I participated in the ICFP programming contest last weekend with a group of friends. We had a great time with the event and learned a ton. I thought I should share two interesting insights with others that might appreciate them.

    First, YARV looks very promising for some general speed increases in Ruby. If you are not familiar with YARV, that's the virtual machine that will run Ruby 1.9. During the contest, we ran into some performance issues with our Ruby solution and after we had optimized all we could think of, we decided to try running our entry on the experimental YARV VM to see if it was faster there. Good news: it was a lot faster.

    Please do not take these numbers as anything more than very non-scientific observations, but we did notice a huge speed increase on YARV. We were reliably waiting around 15 minutes for one section of our program to run on Ruby 1.8.4, but when we introduced YARV the same section generally ran in just under seven minutes. You heard me right there, it was over twice as fast. I think that's very promising news for the future of Ruby.

    Read more…

  • 16

    JUL
    2006

    String Has Other Methods Besides =~/match() and sub()

    Ask anyone who knows me and they will tell you I'm a huge fan of regular expressions. I use them all the time and my FasterCSV library is a regular expression powered parser. However, even I know they are not for everything, and lately I keep running into almost comical examples of misuse. Here are some of my favorites.

    First, we have:

    str =~ /=/
    

    That snippet is like calling for a military escort (the regular expression engine) to see you safely to the grocery store down the block. That's fun, but probably overkill. In this case, a call to include?() will do the trick:

    str.include?("=")
    

    That may be more like riding your bike to the grocery store, but it gets the job done and is a bit faster to boot.

    Funny example number two. I've seen this before:

    str =~ /\Aquit\Z/
    

    Again, the regular expression engine appreciates the love, but you really just want ==:

    str == "quit"
    

    Even for some of the fancier stuff, you don't need a full blown regular expression. For example, this:

    Read more…

  • 8

    JUL
    2006

    The Books are Wrong About Logger

    I've read several books that introduced the standard Logger library and they all agree on one thing: you can't customize the output. That's so last version in thinking! Behold…

    Here's a trivial Logger script, showing basic functionality:

    #!/usr/bin/env ruby -w
    
    require "logger"
    
    def expensive_error_report
      sleep 3  # Heavy Computation Simulation (patent pending)
      "YOU BROKE IT!"
    end
    
    log       = Logger.new(STDOUT)
    log.level = Logger::INFO  # set out output level above the DEBUG default
    
    log.debug("We're not in the verbose debug mode.")
    log.info("We do see informative logs though.")
    if log.error?  # check that this will be printed, before waste time
      log.error(expensive_error_report)
    end
    

    If you run that you will see:

    I, [2006-07-08T11:17:19.531943 #340]  INFO -- : We do see informative logs though.
    E, [2006-07-08T11:17:22.532424 #340] ERROR -- : YOU BROKE IT!
    

    Now everyone has always known you can format the date and time display using a strftime() compatible pattern:

    #!/usr/bin/env ruby -w
    
    require "logger"
    
    def expensive_error_report
      sleep 3
      "YOU BROKE IT!"
    end
    
    log                 = Logger.new(STDOUT)
    log.level           = Logger::INFO
    log.datetime_format = "%Y-%m-%d %H:%M "  # simplify time output
    
    log.debug("We're not in the verbose debug mode.")
    log.info("We do see informative logs though.")
    if log.error?
      log.error(expensive_error_report)
    end
    

    Read more…

  • 13

    JUN
    2006

    Do I Need (These Parentheses()?)

    If you came to Ruby via the Learn to Program book or just don't yet have a consistent set of rules for when you do and don't need parentheses in Ruby code, this post is for you.

    I have nothing against Learn to Program, just to be clear. A member of my family is learning Ruby from it and it's going pretty well. I recommend it. However, Chris is a little inconsistent with his use of parentheses in the code samples, and worse, he doesn't really give you a good set of rules to decide when to make the choice. No problem. Let me give you the rules.

    I'm a chess player. In learning chess, you really go through two phases. First, you learn the rules of strategy. These will make you good because the rules are designed to help you avoid common mistakes. Now, to get great, you go through the second phase: learning when to break the strategy rules. Ruby is exactly the same.

    Here's the only rule of strategy you need to learn to get good: methods need parentheses around their arguments.

    Read more…