Archive for category Tutorial
MacRuby tips: browse for folder or file dialog
Posted by Matt Aimonetti in Tutorial, macruby on October 25th, 2009
This is yet another pretty simple tip.
Use case: let say you want your applications users to choose one or multiple files or folder on their file system. A good example would be that you want the user to choose a file to process or a folder where to save some data.
![]()
In the example above, I added a browse button and a text field.
I would like my users to click on the browse button, locate a folder and display it in the text field.
In your MacRuby controller, use a simple action method as well as an accessor to the text field:
1 2 3 4 | attr_accessor :destination_path def browse(sender) end |
Now, in Interface builder bind the destination_path outlet to the text field you want to use to display the path and bind the button to the browse action.
Let’s go back to our action method and let’s create a dialog panel, set some options and handle the user selection:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | def browse(sender) # Create the File Open Dialog class. dialog = NSOpenPanel.openPanel # Disable the selection of files in the dialog. dialog.canChooseFiles = false # Enable the selection of directories in the dialog. dialog.canChooseDirectories = true # Disable the selection of multiple items in the dialog. dialog.allowsMultipleSelection = false # Display the dialog and process the selected folder if dialog.runModalForDirectory(nil, file:nil) == NSOKButton # if we had a allowed for the selection of multiple items # we would have want to loop through the selection destination_path.stringValue = dialog.filenames.first end end |
That’s it, your user can now browse for a folder and the selection will be displayed in the text field. Look at the NSOpenPanel documentation for more details on the Cocoa API.
MacRuby tips: capturing keyboard events
Posted by Matt Aimonetti in Tutorial, macruby on October 9th, 2009
If you are writing any type of games you might want your users to interact with your application using their keyboards.
This is actually not that hard. The approach is simple and fast forward if you are used to Cocoa.
Everything starts in Interface Builder, add a custom view instance to your window.

Now switch to your project and a new file with a class called KeyboardControlView and make in inherit from NSView. We are creating a subview of NSView so we will be able to make our top view “layer” use this subclass.
class KeyboardControlView < NSView attr_accessor :game_controller def acceptsFirstResponder true end end
As you can see in the example above, I added an attribute accessor. attr_accessor class method creates getters and setters. It’s basically the same as writing:
def game_controller=(value) @game_controller = value end def game_controller @game_controller end
MacRuby is keeping an eye on these accessors and let bind outlets to them.
But let’s not get ahead of ourselves, we’ll keep that for another time.
Let’s go back to our newly created class. Notice, we also added a method called `
acceptsFirstResponder` and returns true. acceptsFirstResponder returns false by default.
But in this case we want it to return true so our new class instance can be first in the responder chain.
Now that our class is ready, let’s go back to Interface Builder, select our new custom view and click on the inspector button.

Click on the (i) icon and in the Class field choose our new KeyboardControlView.
Yep, our new class just shows up by magic, it’s also called the lrz effect, just don’t ask ![]()
So now when our application starts, a new instance of our NSView class is created and Cocoa will call different methods based on events triggered.
The two methods we are interested in reimplementing are keyDown and keyUp. They get called when a key gets pressed or released.
def keyDown(event) characters = event.characters if characters.length == 1 && !event.isARepeat character = characters.characterAtIndex(0) if character == NSLeftArrowFunctionKey puts "LEFT pressed" elsif character == NSRightArrowFunctionKey puts "RIGHT pressed" elsif character == NSUpArrowFunctionKey puts "UP pressed" elsif character == NSDownArrowFunctionKey puts "DOWN pressed" end end super end
I don’t think the code above needs much explanation. The only things that you might not understand are ‘event.isARepeat’. This method returns true if the user left his/her finger on the key. The other thing is the use of the ‘super’ call at the end of the method. Basically, we reopened a method that was already defined and we don’t want to just overwrite it, we just want to inject out code within the existing method, so once we are done handling the event, we just pass it back to original method.
Final result:
class KeyboardControlView < NSView attr_accessor :game_controller def acceptsFirstResponder true end def keyDown(event) characters = event.characters if characters.length == 1 && !event.isARepeat character = characters.characterAtIndex(0) if character == NSLeftArrowFunctionKey puts "LEFT pressed" elsif character == NSRightArrowFunctionKey puts "RIGHT pressed" elsif character == NSUpArrowFunctionKey puts "UP pressed" elsif character == NSDownArrowFunctionKey puts "DOWN pressed" end end super end # Deals with keyboard keys being released def keyUp(event) characters = event.characters if characters.length == 1 character = characters.characterAtIndex(0) if character == NSLeftArrowFunctionKey puts "LEFT released" elsif character == NSRightArrowFunctionKey puts "RIGHT released" elsif character == NSUpArrowFunctionKey puts "UP released" elsif character == NSDownArrowFunctionKey puts "DOWN released" end end super end end
Now it’s up to you to handle the other keystrokes and do whatever you want. That’s it for this tip, I hope it helps.
Ruby, Rack and CouchDB = lots of awesomeness
Over the weekend, I spent some time working on a Ruby + Rack +CouchDB project. Three technologies that I know quite well but that I never put to work together at the same time, at least not directly. Let’s call this Part I.
Before we get started, let me introduce each component:
- Ruby : if you are reading this blog, you more than likely know at least a little bit about, what I consider, one of the most enjoyable programming language out there. It’s also a very flexible language that lets us do some interesting things. I could have chosen Python to do the same project but that’s a whole different topic. For this project we will do something Ruby excels at: reopening existing classes and injecting more code.
- Rack: a webserver interface written in Ruby and inspired by Python’s WSGI. Basically, it’s a defined API to interact between webservers and web frameworks. It’s used by most common Ruby web frameworks, from Sinatra to Rails (btw, Rails3 is going to be even more Rack-focused than it already is). So, very simply put, the webserver receives a request, passes it to Rack, that converts it, passes it to your web framework and the web framework sends a response in the expected format (more on Rack later).
- CouchDB: Apache’s document-oriented database. RESTful API, schema-less, written in Erlang with built-in support for map/reduce. For this project, I’m using CouchRest, a Ruby wrapper for Couch.
Goal: Log Couch requests and analyze data
Let’s say we have a Rails, Sinatra or Merb application and we are using CouchRest (maybe we are using CouchRest and ActiveRecord, but let’s ignore that for now).
Everything works fine but we would like to profile our app a little and maybe optimize the DB usage. The default framework loggers don’t support Couch. The easy way would be to tail the Couch logs or look at the logs in CouchDBX. Now, while that works, we can’t really see what DB calls are made per action, so it makes any optimization work a bit tedious. (Note that Rails3 will have some better conventions for logging, making things even easier)
So, let’s see how to fix that. Let’s start by looking at Rack.
Rack Middleware
Instead of hacking a web framework specific solution, let’s use Rack. Rack is dead simple, you just need to write a class that has a call method.
In our case, we don’t care about modifying the response, we just want to instrument our app. We just want our middleware to be transparent and let our webserver deal with it normally.
Here we go … that wasn’t hard, was it? We keep the application reference in the @app variable when a new instance of the middleware is created. Then when the middleware is called, we just call the rest of the chain and pretend nothing happened.
As you can see, we just added some logging info around the request. Let’s do one better and save the logs in CouchDB:
Again, nothing complicated. In our rackup file we defined which Couch database to use and we passed it to our middleware (we change our initialize method signature to take the DB).
Finally, instead of printing out the logs, we are saving them to the database.
W00t! At this point all our requests have been saved in the DB with all the data there, ready to be manipulated by some map/reduce views we will write. For the record, you might want to use the bulk_save approach in CouchDB which will wait for X amount of records to save them in the DB all at once. Couch also let’s you send new documents, but only save it to the DB every X documents or X seconds.

As you can see, our document contains the timestamps and the full environment as a hash.
All of that is nice, but even though we get a lot of information, we could not actually see any of the DB calls made in each request. Let’s fix that and inject our logger in CouchRest (you could apply the same approach to any adapter).
Let’s reopen the HTTP Abstraction layer class used by CouchRest and inject some instrumentation:
Again, nothing fancy, we are just opening the module, reopening the methods and wrapping our code around the super call (for those who don’t know, super calls the original method).
This is all for Part I. In Part II, we’ll see how to process the logs and make all that data useful.
By the way, if you make it to RailsSummit, I will be giving a talk on Rails3 and the new exciting stuff you will be able to do including Rack based stuff, CouchDB, MongoDB, new DataMapper etc..
Get on Merb Edge pre 1.0
Posted by Matt Aimonetti in Tutorial on October 4th, 2008
Merb 1.0 is almost ready to be pushed out and you might be impatient to start playing with some of the goodies not yet available in the latest stable release. Before getting started, you should know that not everything has been ironed out yet so don’t expect to have a fully stable Edge.
The easiest way to get started requires that you have git installed as well as a gem called thor.
I let you take care of installing git on your machine, Ruby dev without git became quite challenging since GitHub started ruling the Ruby OSS world.
sudo gem install wycats-thor -s http://gems.github.com

Hops, used primarily as a flavoring and stability agent in beer, and also in other beverages and in herbal medicine.
Thor is a sort if mix between rake, sake with a better argument parser and based on Ruby classes.
Thor on its own won’t be very helpful, we need some thor tasks.
Create a folder where you want to store Merb’s source code and cd in it.
Once there download the latest merb thor tasks:
curl -L http://merbivore.com/merb.thor > merb.thor
You can now look at the available task by doing
thor -T
problems with urls in Merb HEAD?
Posted by Matt Aimonetti in Misc, Tutorial on September 30th, 2008
I actually run into a small problem when updated an older Merb app. Here was how my router looked like:
Merb::Router.prepare do |r| r.resources :channels do |channels| channels.resources :shows do |shows| shows.resources :episodes end end end
But after updating to the latest version of Merb, I got links looking like:
http://localhost:4000/channels/#<Channel:0x27b7300>/shows
The first thing to do is to read Carl’s wiki about the latest Router changes.
Carl explains that things got cleaned up in the router code and my routes should now look like:
Merb::Router.prepare do |r| r.resources :channels do resources :shows do |shows| resources :episodes end end end
However that won’t be enough.. You see my url used to look like that:
url(:channel_shows, :channel_id => channel)
Now I can simplify it to:
url(:channel_shows, channel)
That still won’t fix the problem, since the real problem comes from the fact that I was on Merb HEAD but not DataMapper HEAD. Updating DM clears things up. That’s the price to pay to be on HEAD
FYI the problem comes from the fact that DM doesn’t add a to_params method to its objects. Rails users might recognize that method used to convert an object into a string to create a route, something not really ORM agnostic and frowned upon by the DM/Merb teams.
Merb lets you specify the param to use for your routes using the identify method. Read Carl’s wiki page for more cool stuff and see how to create some cool stuff like url slugs etc..
Note that even if you are using ActiveRecord, you’ll need to update merb_activerecord as the new identify rules were updated in the ORM plugins.
Write your own custom DataMapper adapter
Posted by Matt Aimonetti in News, Tutorial on September 29th, 2008
If you read this blog, you probably know that Merb‘s best ORM friend is DataMapper.
Merb works very well with ActiveRecord and Sequel but most of the Merbivores get excited about DataMapper.
DataMapper has a lot of cool stuff going for it. I’m planning on writingi few articles about what I particularily like with DM and some of the misconceptions.
I’m going to give a talk about DataMapper during MerbCamp and something I want to cover is the fact that you can write DM adapters for virtually anything. From an adapter for couchdb (available in dm-more) to an adapter for SalesForce API. That’s the kind of stuff that gets me excited, a bit like what Ambition does but built-in in DM.
So, I decided to take some advise from Yehuda and dkubb and wrote my own adapter for Google Video. I had just finished a gem to retrieve google videos for a given google user and thought it would be a perfect exercise to mix a http-scraper with a DM adapter.
Deploying a bundled merb app (merb 0.9.7+)
Posted by Matt Aimonetti in Tutorial on September 23rd, 2008
Since Merb 0.9.7 the Merb team decided to change the way you can bundle an app. Until 0.9.7 you would use the merb-freezer plugin which was supporting git submodules and gems. The only problem was that you still had to install merb-freezer on your server and it had to stay in sync with your app… kinda lame
Instead, after a lot of discussions, we decided to add this feature to merb-core and let you bundle all your dependencies in a bundled gem folder. No more support for git submodules as they are hard to keep track of and don’t handle dependencies very well (not at all).
The new freezing strategy is very well described in this merbunity article. However it doesn’t really explain how to deploy a bundled app.
So let’s imagine for a second that we bundle our app, generated the scripts needed to start merb/rake etc…



