Ruby Tuesday #16 Part 2 : IronRuby news

29 07 2008

At OSCON last week, John Lam made a number of announcements about IronRuby (and speaking of OSCON, you should check out the announcements Sam Ramji made, too.)  In summary:

There’s a binary release of IronRuby, which includes the standard Ruby libraries.

An ironruby-contrib project has been established – another way to get involved in the IronRuby community.

A set of changes to RubySpec have been submitted.

The full blog post on the IronRuby announcements is here.  Well worth reading in full.





Ruby Tuesday #12 : Twitter on Shoes

1 07 2008

Last week I hoped I would have finished my Twitter client in Shoes by now.  Unfortunately, I ran into some issues with Shoes (such as redraws where every control ends up superimposed on top of itself but pushed out to the left and down.)  The most serious of these issues is its frequent reluctance to allow me to enter text into text boxes (or edit_lines in shoe parlance.)  I’ve found that if I click off the Shoes window and back in, it will let me enter text and click buttons.  Not ideal, but it seems to work - I even managed to tweet using my new client.  So, without further ado, here is the code:

require 'Twitter'

Shoes.app :title => "Twitter Shoes", :height => 750, :width => 750 do
    flow :margin => 10 do
         stack :width => 700, :height => 90, :top => 10, :left => 10 do
            flow :margin => 5 do
                para "Username"
                @username = edit_line :height => 30, :width => 120, :left => 100
            end
            flow :margin => 5 do

            end
            flow :margin => 5 do
                para "Password"
                @password = edit_line :secret => true, :height => 30, :width => 120, :left => 100
            end
        end
        stack :height => 90, :top => 100, :left =>10, :width => 700 do
            flow :margin => 5 do
                para "Status", :top => 10
                @status = edit_line :height => 30, :width => 270, :left => 100, :top => 10
                button "Update", :height => 30, :width => 100, :left => 400, :top => 10 do
                    username = @username.text
                    password = @password.text
                    status = @status.text
                    if username.empty?
                        alert "You must enter a username."
                    elsif password.empty?
                        alert "You must enter a password."
                    elsif status.empty?
                        alert "You must provide a status."
                    else
                        client.update(status, username, password)
                    end
                end
                button "Update Timeline", :height => 30, :width => 120, :left => 550, :top => 10 do
                    username = @username.text
                    password = @password.text
                    if username.empty?
                        alert "You must enter a username."
                    elsif password.empty?
                        alert "You must enter a password."
                    else
                        timeline = ""
                        translator.xml_to_tweets(client.download_friends_timeline(username, password)).each do |tweet|
                            timeline << "#{tweet.user.screen_name} says #{tweet.text}\n\n"
                        end
                        @tweets.replace timeline
                    end
                end
            end
        end
        stack :height => 550, :top => 200, :width => 700, :margin => 10, :left => 10 do
            background "#eee"
            @tweets = para ""
        end
    end
end

You can also download it here.  Most of the changes are in the layout.  I started the layout from scratch.  I’d suggest reading the manual that you can find here.  It’s not exactly comprehensive, but it points you in the right direction.  If you’re like me, you’ll find that changing one value has unexpected and seemingly unconnected consequences.  Still, by changing one thing at a time and sticking to a very basic design I got there.

So, you can tweet from Shoes.  Shoes uses Ruby and has some intriguing ideas (like the HTMLish layout concepts), but there’s a lot to be said for a good visual designer with drag and drop.   Gets the same job done more quickly.  Add the ability to edit by hand and we’re all happy.  I’m still in search of my ideal Twitter client, though…





Ruby Tuesday #11 Update : First Steps with Shoes

24 06 2008

When I left my last post, I had been encountering some crashes with Shoes.  So, I took the Ruby code I’d written, installed Shoes on a Mac (running Leopard) and, hey presto, it worked.  I haven’t tested another Vista PC to see if it’s Shoes or the PC I was using.  Here’s the code:

require 'Twitter'

translator = Translator.new
client = Client.new

Shoes.app :title => "Twitter Shoes", :height => 750, :width => 750 do
  background rgb(240, 250, 208 )
  stack :width => 700, :height => 1.0, :margin => 20 do
    background "#eee", :radius => 12
    border "#00D0FF", :strokewidth => 3, :radius => 12
    stack :margin => 20 do
      button "Get Timeline" do
        alert("Username is {#@username.text} and password is {#@password.text}")
        timeline = ""
        translator.xml_to_tweets(client.download_friends_timeline(@username.text, @password.text)).each do |tweet|
        timeline << "#{tweet.user.screen_name} says #{tweet.text}\n\n"
      end
      @label.replace timeline
      #alert "done"
    end
  end
  stack :height => 550, :margin => 20 do
    background "#eee"
    @label = para ""
  end
  stack :margin =>20 do
    @username = edit_line :height =>50, :width => 100
    @password = edit_line :secret => true, :height =>50, :width => 100
   end
 end
end

So, what needs to be done next now is to provide a way to tweet from the Shoes form.  And it could do with some tidying up.

To help if you’re following this series, I’ve posted the source files for Twitter.rb and App.rb.

Oh, and there’s a space between 208 and the closing bracket in the line beginning background because if I don’t put the space in, WordPress converts the sequence 8 followed by a bracket to a smiley face wearing sunglasses.  Like this 8) .  Which looks a bit weird in code.





Ruby Tuesday #11 : First Steps with Shoes

24 06 2008

Last week, I decided that Shoes was the toolkit I’d use to build a GUI for the Twitter client I’ve built in Ruby. So, I downloaded Shoes and installed it on a machine running Vista. There’s a bunch of samples that come with Shoes - to run the Timer, for example, type Shoes samples\timer.rb.

Before I got any further, I checked my feedreader and noticed that Scott Hanselman had blogged about Shoes - and said that it’d be a grat idea to build a Twitter client in Shoes. Timing is everything. Let’s put our shoes on.

I like to start simple. In fact I pretty much like to end simple, too. Anyway, I thought I’d start out with a button that downloads the public timeline when you press it. Here’s the code:

require 'Twitter'

translator = Translator.new
client = Client.new 

Shoes.app :height => 150, :width => 250 do
   background rgb(240, 250, 208 )
   stack :margin => 10 do
     button "Get Public Timeline" do
       timeline = ""
       translator.xml_to_tweets(client.download_public_timeline).each do |tweet|
         timeline << "#{tweet.user.screen_name} says #{tweet.text\n"
       end
       @label.replace timeline
     end
     @label = para ""
   end
end

OK, a couple of confessions. The first is that it looks pretty awful. The second is that on my machine the require was causing an exception in Shoes, so I replaced it with the code from Twitter.rb. I’ve shown the code here with require because it should work and it’s much simpler to read.

Let’s see if we can tidy that up a bit. There’s a couple of issues. There’s no scrollbar for the tweets and all the tweets run into each other. By putting stacks inside a containing stack, we should be able to sort that out. Here goes:

require 'Twitter'

translator = Translator.new
client = Client.new

Shoes.app :title => "Twitter Shoes", :height => 750, :width => 750 do
   background rgb(240, 250, 208 )   stack :width => 700, :margin => 20 do
     background "#eee", :radius => 12
     border "#00D0FF", :strokewidth => 3, :radius => 12
     stack :margin => 20 do
       button "Get Public Timeline" do
         timeline = ""
         translator.xml_to_tweets(client.download_public_timeline).each do |tweet|
           timeline << "#{tweet.user.screen_name} says #{tweet.text\n\n"
         end
         @label.replace timeline
       end
     end
     stack :height => 650, :margin => 20 do
        background "#eee"
        @label = para ""
     end
   end
end

I borrowed the colours and border from the jot example in the samples that come with Shoes. I think that looks much better. What would be even better is if it downloaded your friends timeline (i.e. you and those you follow.) I put some text boxes (edit_box) in to enter the username and password and even figured out how to mask the password (:secret => true) but started to have some issues with Shoes crashing. So, next week’s task will be to see if I can overcome the crashing and get a more functional client.





Firefix

22 06 2008

Having installed Firefox 3 recently, I was having some trouble with extensions.  They wouldn’t install and those that were installed didn’t do what they said they would on restarting Firefox.  After a little headscratching, I found this article.  And Firefox is fixed.





Ruby Tuesday #10 Part 1 : Studying Form

17 06 2008

The next task I had set myself in my Ruby learning journey was to write a GUI for the Twitter client I have created.  A quick squiz around the internet reveals a number of potential frameworks.  In no particular order, here’s some I found:

FXRuby - "a library for developing powerful and sophisticated cross-platform graphical user interfaces."  I was toying with the idea of writing a weak and crude GUI, but this may still be the right choice.

Konundrum - "Very complete bindings to both the KDE API and the Qt APIs."  Very complete is clearly a good thing - none of your bog standard completeness here.  Now, what’s Qt?  It’s a "cross-platform application framework for desktop and embedded development" according to its authors, Trolltech, with "an intuitive API and a rich C++ class library."

Ruby/Tk - there seems to be Ruby bindings for the Tk toolkit. Tk is a "Tcl extension, written in C, designed to give the user a relatively high level interface to his or her windowing environment."  Tcl, in turn, is a "a powerfully simple, open source-licensed programming language."  Hmm.  Does all this sound a little obtuse and slightly recursive to you, too?

Ruby-GNOME2 -  "a set of Ruby language bindings for the GNOME 2.0 development environment."  GNOME "offers an easy to understand desktop for your GNU/Linux or UNIX computer." And lots of CAPITALS.  *nix only is a dealbreaker for me - although the documentation includes mention of Ruby/Gtk2, which uses Gtk+, which runs on Windows.  Could be clearer, but if you’re a fan of the esoteric this could be a good choice.

Shoes - "a very informal graphics and windowing toolkit."  Here’s a helpful poster thingy about it.

Of course, with IronRuby I could also use Silverlight.  I haven’t covered IronRuby yet, so I’ll leave Silverlight for another Ruby Tuesday.  For those of you who can’t wait, I’d suggest a little peek here.

Is all this choice a good thing?  Or does it distract me from building a GUI by leading me to have to find out some more about each framework / toolkit?  As good a concept as choice is, I’m not sure what the choice here really is.  I can choose between a bunch of frameworks that do more or less the same thing.  So unless anyone has a better idea, I’m going to plump for Shoes on the basis that it has the best, albeit extremely silly, name.





Ruby Tuesday #7 Part 1: Even Twittier

27 05 2008

Having managed to download the public timeline and output in a friendly format, the next task was to access some other methods of the Twitter API.  A couple of other timeline methods exist: friends_timeline and user_timeline.  Both can take the username as part of the URL.  How hard will it be to update the code to accommodate these calls?

One of the first things I noticed was that each of the URL’s for the Twitter API have the same base (http://twitter.com/statuses), so it’d be good to split this out.  I updated the get_url method accordingly:

def get_url(base_address, path)
  url = URI.parse(base_address + path)
  req = Net::HTTP::Get.new(url.path)
  res = Net::HTTP.start(url.host, url.port) {|http| http.request(req)}
  res.body
end

I tried to use the join method of URI, but it seemed to strip out the http:// part of the URL.  The next step was to create a new class called Client (in the Twitter file.)  It looks like this:

class Client
  BASE_ADDRESS = 'http://twitter.com/statuses'

  def download_public_timeline
    download_timeline('/public_timeline.xml')
  end

  def download_friends_timeline(username)
    download_timeline("/friends_timeline/#{username}.xml")
  end

  def download_user_timeline(username)
    download_timeline("/user_timeline/#{username}.xml")
  end

  private

  def download_timeline(path)
    get_url(BASE_ADDRESS, path)
  end

end

For those of us learning Ruby, there’s a couple of interesting things to note here.  The first is the constant - it’s denoted by the use of capital letters.  It’s not really a constant - I could change the value if I liked, but Ruby convention is that if it begins with a capital letter then it’s a constant.  Those of us coming from a C# background may be surprised to learn that this constant could be used anywhere in the program - it is not limited to the scope of the class in which it is defined.  The constant can be qualified by the class name (e.g. Client::BASE_ADDRESS) for clarity.  The second point of interest is the use of the word private.  Any method defined after the use of private will be have private visibility (instances of the class and subclasses) until the end of the class or the words public or protected.  Methods are public by default.  Once again, private is not a keyword but a method specifies that the following method definitions are private.

All that’s left is to call these methods from the main body - which looks like this:

require 'Twitter'

$KCODE = "u"

translator = Translator.new
client = Client.new

translator.xml_to_tweets(client.download_public_timeline).each do |tweet|
  puts "#{tweet.user.screen_name} says #{tweet.text}"
end

translator.xml_to_tweets(client.download_friends_timeline('put_your_username_here')).each do |tweet|
  puts "#{tweet.user.screen_name} says #{tweet.text}"
end

translator.xml_to_tweets(client.download_user_timeline('put_your_username_here')).each do |tweet|
  puts "#{tweet.user.screen_name} says #{tweet.text}"
end

The funny looking line near the top ($KCODE…) sets the text encoding to be UTF-8.   I set this because there is some character data in the timeline that would look funny otherwise.  (I was using Netbeans when I put this in and it had no effect - garbled output for some character data - whereas at a terminal calling the program I got the results I expected, I haven’t tried this yet with Sapphire in Steel.)

It was fairly straightforward to add this extra functionality.  I fell into the trap of using C# style names, which I corrected before writing this post, so I’m clearly still thinking in C#.   And even though the Client class is fairly concise, I wonder if it could be made more concise yet.  The next step is to add the ability to tweet directly from the Ruby program.





Seeing the Big Picture

27 05 2008

K. Scott Allen’s post on the limits to visual tools is an interesting read.  The main contention is that visual tools don’t scale and consequently have a limit.  The examples in the post back up this point.  I wonder if this is a problem with visual tools per se, a limitation of current tools or a misuse of the tools.  It may be a combination of these factors.  The first question to ask is: do text based tools scale well?  The good news is that we can split a system up into an arbitrary number of files.  This is great for understanding the contents of a file – but the system as a whole is still very difficult to understand, especially for those coming to the system cold.  Putting everything into one diagram is the equivalent of putting all our code into one text file – I’m going to assume you agree with me that that’s a bad idea for all but the most trivial of system.  With a well factored codebase, the best route into the system for most people, in my experience, is some sort of graphical overview – the key here being that it must be at the right level of abstraction.

In creating and reviewing architectural documents and walkthroughs, I’ve often faced the same issue of getting the right amount of information into diagrams.  There is a temptation to have one diagram that shows everything – this temptation should be resisted as it leads to confusion.  Having a number of views of a model (each at differing levels of abstraction and with a different perspective and focus) is the best way I’ve found of distilling the right amount of information.  What we need from the tooling is a way to link the views together.  When you think about it, the principle here is similar to that used in splitting up a codebase into multiple files.  Diagrams and models are, of course, not text free – but in the right context one diagram can save a lot of time and effort.

So, I’m not convinced that there is an inherent quality of visual tools that limits their ability to scale – but the way in which we use them and some of the functionality provided may need to change to accommodate scale.  Another thing to consider is that models can be represented with both text and diagrams – potentially allowing different people to use representations that are closest to their natural strengths.





Ruby Tuesday #6 : A little XML

20 05 2008

Last week I wrote some code to download the public timeline from Twitter.  The public timeline is in XML format, so we need a little code to translate it into something more readable.  Before getting to the XML reading, I moved the code from last week into a new file called, very imaginatively, Twitter.rb.  I also discovered that the name I gave the method (getUrl) isn’t very Rubylike, so I changed it (to get_url).  Now, I’m not the biggest fan of underscores, but part of this learning Ruby business is to learn the culture and customs as well as the language itself.

Next, I decided that it would be good to have a class representing a tweet and another class representing a user.  I put both of them in the Twitter file.  Here are those classes:

class Tweet  attr_reader :created, :id, :text, :source, :truncated, :user 

  def initialize(created, id, text, source, truncated, user)    @created = created    @id = id    @text = text    @source = source    @truncated = truncated    @user = user  endend

class User  attr_reader :id, :name, :screen_name, :location,     :description, :image_url, :url, :protected 

    def initialize(id, name, screen_name, location, description, image_url,    url, protected, followers_count)       @id = id       @name = name       @screen_name = screen_name       @location = location       @description = description       @image_url = image_url       @url = url       @protected = protected       @followers_count = followers_count    endend

I’ve used the attr_reader method to create read-only attributes which are set in the initialise method of each class.  For those who, like me, are new to Ruby the initialise method performs a similar purpose to a constructor.  The funny @ signs denote instance variables.  I could have made these classes by using attr_accessor (which creates a getter and a setter), but I like this style of object.  I expect I’ll find a simpler way of doing it as I go along.

Next we need to read XML into these objects.  I created a class called Translator and in it created a method called xml_to_tweets (and a method it calls called element_to_user.)  Here’s the class:

class Translator  def xml_to_tweets(xml)    tweets = []    xml_document = Document.new(xml)    root = xml_document.root    root.elements.each("status") do |element|      tweets << Tweet.new(element.elements["created_at"].text,      element.elements["id"].text,      element.elements["text"].text,      element.elements["source"].text,      element.elements["truncated"].text,      element_to_user(element.elements["user"]))    end    tweets  end


  def element_to_user(element)    User.new(element.elements["id"].text,    element.elements["name"].text,    element.elements["screen_name"].text,    element.elements["location"].text,    element.elements["description"].text,    element.elements["profile_image_url"].text,    element.elements["url"].text,    element.elements["protected"].text,    element.elements["followers_count"].text)  endend

REXML is a conformant XML processor, so if you’ve done any XML programming before, it’ll be familiar.  Three things to note here.  Firstly, this code is using the REXML library (more info here) so I had to add 2 lines to the top of the file.  Those lines are:

require 'rexml/document'include REXML

Secondly, for my fellow Ruby noobs, note that the value of the last expression in a method is returned (no return statement needed, although you can put it in if it you like.)

Thirdly, for the noobs again, note the array syntax.  A new array is created with the [] syntax and new elements are added with the << operator.

So, all that’s required now is some code to see if it works.  I used this code:

require 'Twitter' 

translator = Translator.new 

translator.xml_to_tweets(get_url('http://twitter.com/statuses/public_timeline.xml')).each do |tweet|  puts "#{tweet.user.screen_name} says #{tweet.text}"end

The output of that is a lot friendlier than the XML I was outputting last week, and it was fairly easy to write.  Next week I’ll need to extend the code to call some of the other methods of the Twitter API. 





Ruby Tuesday #4 : Time to Productivity

6 05 2008

So far I’ve concentrated on setting up an environment.  Meantime, I’ve been reading about Ruby and trying to learn the syntax.  It’s at this point that you wonder if you can ever be productive in the new language.  The syntax is relatively easy – it’s the rest that is more daunting.  The rest is the stuff you take for granted in your preferred language, stuff like how to organise and layout files, how to deploy, what’s in the standard libraries, etc.  It’s like learning a new language: despite a grasp of the grammatical rules, all you can say is “Where might I find the nearest tractor repair shop?” - and you don’t quite understand the response.  This wouldn’t be an issue if you weren’t already proficient in a language because you wouldn’t know how much more you could achieve.

So, the question is how long does it take to become productive and how best to go about learning the real stuff.  From past experience of learning new programming languages, the answer seems to be build something - in addition to continuing to read as much as possible.   What should that something be?