Saturday, January 27, 2007

"Installing" net/https library in Ruby

This isn't written anywhere that I've looked, so it's either obvious, or I just missed the boat. But basically, in order to use the "net/https" library, you don't need to download it. It's included in the build of Ruby 1.8.4+

However, what you do need to install is both openssl, and the ruby-openssl packages for it in ubuntu in order for it to be working. Tip!

How to install Ruby 1.8.5 from source on Ubuntu

Well, it ends up that installing Ruby 1.8.5 and the associated Gems is a pain on Ubuntu. I'm here to take away that pain, yo.

Installing Ruby 1.8.5 from source

First, get the source tarball of 1.8.5 from the ruby lang web page, and put it in /usr/local/src
sudo tar -xvzf ruby-1.8.5-p12
cd ruby-1.8.5-p12
sudo ./configure
sudo make
sudo make install
If all goes well, you're in business. But if it complains about "cannot open crt1.o"
(which is likely on Ubuntu), you'll divine on google that it needs a "glibc-devel-2.3.3-74.i386" package. But I've done the legwork already, and under ubuntu, it's actually called "libc6-dev"
sudo apt-get install libc6-dev
So try making Ruby again. It should be ok. If not, well, it's not documented here, since I didn't run into that problem.

What I did run into was more pain installing Gems.

Installing Ruby Gems from source


Again, go get the source tarball of ruby gems, and put it into /usr/local/src
sudo tar -xvzf rubygems-0.9.1
cd rubygems-0.9.1
sudo ruby setup.rb

Now, if all is well, you're golden. But since this is Ubuntu, it's likely that you're missing zlib. So, some people seemed to have been able to get it to work from using the "zlib-ruby" package. What I had to do was install zlib from source.

Installing Ruby Zlib from source


Get the Ruby Zlib source and again put it into /usr/local/src/
sudo tar -xvzf ruby-zlib-0.6.0
cd ruby-zlib-0.6.0
sudo ruby extconf.rb

If that didn't work, most likely, you got a bunch of stuff that said:
checking for deflateReset() in -lz... no
checking for deflateReset() in -llibz... no
checking for deflateReset() in -lzlib... no

That means that you need the headers for zlib. So install the package "zlib1g-dev"
sudo apt-get install zlib1g-dev

Then try it again. That should work, and once you get zlib installed, you can get gems up and running.

Friday, January 05, 2007

How to grep for the negation or not or something on the command line.

I've always wondered how to grep for the negation of something. When SubClipse messes up, I end up spending time in the terminal. I hate it. It should at least be able to recover from itself.

Anyway, I wanted to find the difference between two directories. So for diff, you simply use:

diff -rq directory1/ directory2/

And this will give you a slew of which files are different or same. But it'll give you all this stuff about .svn directories that you don't care about. So how do you grep for the NOT of something? I don't know, the regex for it (if someone cares to divulge, I'd appreciate it), but grep has a switch that does this for you:

diff -rq directory1/ directory2/ | grep -v 'svn'

And voila, it only gives you the differences other than paths with 'svn' in them.

Wednesday, January 03, 2007

Testing link_to_remote AJAX calls in Rails

I wanted to be able to test ajax methods in a rails controller, but I wasn't able to find good tutorials on this topic...so either no one uses it, or everyone else just got it right away.

let's say I have the following made up method:

def edit_importance
@friend = Friend.find(params[:id])
@friend.update_attributes(:importance => params[:importance]) unless @friend.nil?
render :partial => "shared/stars"
end
That gets called in the view by:
<%= link_to_remote(image_html, :update => "friend_stars_#{@friend.id}",
:url => { :controller => "friends", :action => :edit_importance,
:id => @friend.id, :importance => nth }) %>

How does this get tested? Well, I figured out there was an xml_http_request call in ActiveController::Testprocess, but I had no idea what to put in the parameters.
xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil)
It ends up that reading RFC 2616 (HTTP) helped, and request_method is just :get, :put, :post, :delete, etc.

So to test out this, all you have to do is:
 def test_edit_importance
jon_lee = friends(:jon_lee) # from a fixture
old_importance = jon_lee.importance

xml_http_request :put, :edit_importance, { :id => jon_lee.id, :importance => 3 }
assert_template "_stars"
jon_lee.reload
assert_equal 3, jon_lee.importance
assert_not_equal old_importance, jon_lee.importance
end
Remember to reload the old object, since it will still have the old values. You can also use jon_lee = assign(:friend) after the xml_http_request, if you don't want to reload.

Also note that you can test for returns of partials with assert_template. It just has to be a string with the preceding "_" as per partials convention.

As for testing RJS templates, you'd want to look into the assert_rjs plugin.

Incorrect use of exception handling

Exception handling was never something that I looked much into. I've caught exceptions from libraries before, but when it came to coming up with exceptions to throw, I never gave it too much thought. So I looked it up in detail, and to my horror, I had been using it wrong.

Documenting my stupidity, hopefully, I'll prevent others from doing the same basic mistake.

In a rails controller, there is always a simple case of creating a model, but sometimes, there's value checking.

def create
if params[email] == "bob@uiuc.edu"
flash[:error] = "Bobs at UIUC not allowed"
redirect_to :action => :list
return
end
@friend = Friend.create(params)
unless @friend.save
render :action => :edit
else
flash[:notice] = 'Friend was successfully updated'
redirect_to :action => 'list'
end
end

I thought, "Hey, why not move that error handling code to the end, so it reads better?"

class NoBobsError < Exception; end
def create
raise NoBobsError.new if params[email] == "bob@uiuc.edu"

@friend = Friend.create(params)
raise ActiveRecord::RecordNotSaved.new unless @friend.save

flash[:notice] = 'Friend was successfully updated'
redirect_to :action => 'list'
rescue ActiveRecord::RecordNotSaved
render :action => :edit
rescue Exception
flash[:error] = "Bobs at UIUC not allowed"
redirect_to :action => :list
end

That way, the error handling code doesn't really get in the way of the 'good condition' code. I personally think it's easier to read, though apparently, this is a bad idea apparently, mostly due to overhead costs in running through an exception, even if there were no exceptions thrown, and that I'm essentially using it as a goto statement. And as everyone knows, gotos taste like ass.

Exceptions are to be used when the method or object that the error occurred doesn't know what to do with the error at that time. Therefore, it will throw an exception, and hope that some other part of the code elsewhere up the stack will know what to do with it. And so hence the adage: "throw early, catch late".

So I'm a reformed exception handling abuser. I guess when you have a new hammer, the world looks like a nail, until someone sets you right.


http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html

http://today.java.net/pub/a/today/2003/12/04/exceptions.html