Lyle Johnson just wrote a great tutorial on how to integrate Google Charts into an FXRuby application. This is perfect timing since I’ve been doing some experimenting with FXRuby over the past few days.
Category: Ruby
-
Exploring Google Charts with the gchartrb gem
Google quietly released their new chart generation web service late last year. It’s a dead simple way to build beautiful charts using nothing but URLs. The gchartrb gem wraps Google’s API to make things even easier. InfoQ recently published this article that I wrote. It introduces the basics of the API and gives some examples of how to use gchartrb to create beautiful charts.
-
Installing FXRuby on OS X
Thought I’d do some hacking on FXRuby today. I ran into trouble during the installation so I’m posting the solutions here in case anyone else experiences the same issues.
I attempted installing the fxruby gem first, but didn’t get very far. I ended up having success with the rb-fxruby package for MacPorts so I highly recommend going that route.
Make sure you uninstall and clean the gem if it’s already installed:
gem uninstall fxruby gem clean fxruby
Now install the MacPorts package:
port install rb-fxruby
This might take a while. You may have to run the command twice if you get a failure the first time through. Now copy and paste this script into a .rb file and try running it:
require 'rubygems' require 'fox16' include Fox app = FXApp.new win = FXMainWindow.new(app, 'Hello World') app.create win.show app.run
You should see an error message that looks something like this:
FXRbApp::openDisplay: unable to open display :0.0
It means your X11 terminal isn’t running. You can find it in
/Applications/Utilities. Double click to launch. If you roll with Quicksilver, you should be able to type in X11 and launch it that way. Once launched, run the Ruby script again and you should see a tiny window with the title “Hello World.” -
One week left for Ruby Hoedown proposals
You’ve got about a week left to get your proposals in for a talk at the Ruby Hoedown, the South’s regional Ruby conference. Speakers will receive free admission and an as of yet undetermined honorarium along with dinner the night before the conference. (C’mon, you can’t possibly pass up free food.) Ping proposals@rubyhoedown.com if you have any questions.
-
Ruby Hoedown 2008
The Ruby Hoedown moves to Hunstville, Alabama this year. I’m filling Nathaniel’s place as co-organizer this go round, along with Jeremy McAnally who was the driving force behind the conference last year too. We’re cooking up a good mix of Ruby talks. It’s not too late to get your own proposal in: the deadline is June 2nd. David A. Black and Chris Wanstrath are keynoting so you’re in good company.This year’s conference is shaping up to be another rip-roaring success, with several companies already onboard as sponsors and some nice giveaways in the works. I expect to see y’all down south in Alabama come August to celebrate our favorite language: Ruby!
-
Building arrays of similar objects in Ruby
I often find myself having to build arrays of similar objects in my tests. For example:
def create_user :some_user end users = [create_user, create_user, create_user]
It seems wasteful to repeat the same method call three times. One solution is to use the #times method to append to an array, like this:
users = [] 3.times { users << create_user }This just doesn't seem very elegant, though. It feels like I should be able to collect the results from each method call with a single line of code. I experimented with the multiplication operator to see if it might be able to do what I wanted, but didn't get far.
Here's one possible solution I came up with:
class Integer def of result = [] times { result << yield } result end end users = 3.of { create_user } # returns [:some_user, :some_user, :some_user]The #of method can now be called on an integer. It uses #times to call the given block three times and appends the result to an array which is then returned. Much more elegant. Another way to achieve this on a single line is:
users = (0..2).to_a.collect { create_user }This doesn't feel as nice to me. It's visually complex and, at first glance, the zero-basing of the range hides the fact that we're collecting three items, not two. The benefit is that no reopening of the Integer class is required.
How would you solve this problem?
-
How to filter model data before rendering in Streamlined
One question that seems to come up a lot on the Streamlined mailing list is how best to filter the records that are displayed in the list view using a certain set of conditions. There are several ways of doing this, but the simplest way is to use Rails’ built-in scoping methods in conjunction with an around filter.
For example, say we have a Task model and a TaskController that is Streamlined-enabled. The TasksController will display a list of all Tasks in the system by default. What if we only want to display Tasks for the currently logged-in user? Something like this would work:
around_filter :scope_by_user, :only => [:list, :index] def scope_by_user Task.find_with_user_scope(current_user) { yield } endOnce this code is added to the TaskController, any calls to Task#find within the associated actions, views, and helpers will be scoped. Only tasks belonging to the current user will be listed.
What if we still want to perform an unscoped Task#find within an action? We can eliminate the scoping for a specific block of code using the #with_exclusive_scope method. It looks like this:
Task.with_exclusive_scope { code_that_should_not_be_scoped }And that, folks, is how easy it is to filter lists in Streamlined.
-
raleigh.rb has a podcast
Did you realize that Raleigh’s own Ruby Brigade now has a podcast? Yes ladies and gents, it’s true.
I’ve been recording the last few meetups on my MacBook. The audio quality isn’t half bad. I hope to expand the podcast in the future with non-meetup content. For now, it can serve as a good way to catch up if you’re out of town or otherwise can’t make it to our regular monthly meeting.
-
Fix for fixture_replacement2 when using default methods
I’ve been using the excellent fixture_replacement plugin for several months now and greatly prefer it over traditional fixtures (yes, even foxy fixtures). fixture_replacement2 adds even more goodness to the party. However, I ran into a problem today when trying to use
default_xxxmethods in my example_data.rb file:module FixtureReplacement attributes_for :course do |c| c.name = "Geometry" c.transcript = default_transcript end attributes_for :transcript do |e| e.name = "Joe's Transcript" end endIn “fixture_replacement language” this says that new courses should receive a default name of “Geometry” and should also receive a new transcript with a default name of “Joe’s Transcript.” The example above follows the format given in the fixture_replacement README. When I attempt to use this config file in my Rails 2.0.2 project, though, I get this error:
NameError: undefined local variable or method `default_transcript' for FixtureReplacement:Module at top level in example_data.rb at line 7 ...
Why can’t it find
default_transcript? I have no idea. Digging into the source code reveals thatdefault_transcriptis added to the FixtureReplacement module at runtime, but for some reason it doesn’t ever show up as being available for calling. I don’t have the time or inclination to dig further, but I did find a workaround by changing:c.transcript = default_transcript
to…
c.transcript = c.default_transcript
This makes fixture_replacement happy and all my tests pass. I submitted a patch so hopefully this wrinkle will be ironed out soon. But this should get you by until then.
-
CSV transmogrifies into FasterCSV in Ruby 1.9
Matz let Ruby 1.9 into the wild last month. One nice change (among many) is that Ruby’s painfully slow CSV library has been replaced with James Edward Gray II’s most excellent FasterCSV library. This will most likely break existing code that uses CSV.
From James’ blog:
The methods provided on the CSV object are similar, but the old CSV code used positional parameters where as the new library user a Hash argument syntax (e.g.,
:row_sep => "rn"). That’s going to trip up any non-trivial usage.He also gave an example of how to write CSV code that interoperates with 1.8 and 1.9:
require "csv" if CSV.const_defined? :Reader # use old CSV code here… else # use FasterCSV style code, but with CSV class, here… end
Yes, it’s kind of gross, so just make sure you never have to write it. If you’re going to move to 1.9, move everything and avoid the hassle.
I’m pretty excited about the performance improvements and other enhancements that have been made in 1.9. This is the first major release of Ruby since I began hacking on it back in the day. It’s a thrill to be part of a community that avoids the “machine gun” approach to releases.