Threads can be tough and don’t suit beginners very well. And, well, Ruby threads can tie up the main app thread.
So, Shoes steals the underpinnings of Ajax to give you asynchronous downloads without needing to get into threading. Many of the young Sneakers are building Twitter and Flickr apps; it seemed the morally upright thing to do. In addition, I was able to use these HTTP threads to load remote images in the background. So, in Shoes, images loaded from the web will appear as they load.
Here’s the simple-downloader.rb from the samples that come with Shoes:

To achieve this, Shoes uses platform code for both threading and HTTP. On Windows, CreateThread and WinHTTP. On Linux, pthread and curl. And, on OS X, NSDownload and NSThread.
Downloading is reduced to a single line:
Shoes.app { download "http://shoooes.net/shoes.png", :save => "shoes.png" }
This happens asynchronously, so shoes.png won’t be there yet when this method ends. It might be huge. It might appear an hour later. You can attach a finish event to be notified when the download is complete.
Shoes.app do
download "http://shoooes.net/shoes.png", :save => "shoes.png" do |dl|
alert "Scuse me. Your shoes.png has arrived."
end
end
Omit the :save option and you can get back the download as a string.
Shoes.app do
download "http://hacketyhack.net/pkg/osx/shoes" do |dl|
alert "The latest OS X download is: #{dl.response.body}"
end
end
You can also attach :method, :headers and :body options to the download, if you want to customize the request beyond that. I studied XMLHttpRequest closely and tried to be sure the same things could be done with this.
As for events, you get four of them: start, progress, finish and error. You can either pass proc objects in as options:
Shoes.app do
url = "http://shoooes.net/dist/shoes-0.r905.exe"
status = para "Downloading #{url}"
download url, :save => "shoes.exe",
:start => proc { |dl| status.text = "Connecting..." },
:progress => proc { |dl| status.text = "#{dl.percent}% complete" },
:finish => proc { |dl| status.text = "Download finished" },
:error => proc { |dl, err| status.text = "Error: #{err}" }
end
Or, use the method syntax:
Shoes.app do
url = "http://shoooes.net/dist/shoes-0.r905.exe"
status = para "Downloading #{url}"
get = download url, :save => "shoes.exe"
get.start { |dl| status.text = "Connecting..." }
get.progress { |dl| status.text = "#{dl.percent}% complete" }
get.finish { |dl| status.text = "Download finished" }
get.error { |dl, err| status.text = "Error: #{err}" }
end
The last thing I will mention is that every queued download is attached to the window containing it. When you close the window, the download stops. So, if you’re queueing a download from a temporary popup, be sure to queue it on the main app window.
No comments yet.
You must be logged in to add your own comment.