Sep 30, 2008

Ruby Scoping Gotcha

One little thing you may need to remember when coding in Ruby. Consider this little program:
myArr2D = [ [2, 2], [2, 2] ]

myArr2D.each do |m|
x = m.map { |m| m * 2 }

puts m.class.to_s
end
Intuitively, this should output this:
Array
Array
However it outputs this:
Fixnum
Fixnum
What happens here is that the variable m in the map block overshadows the outer variable m, so that whenever you access the variable m after the call to map, you're accessing the inner variable. This might lead to some unexpected side effects, so make sure you keep it in mind...

Sep 29, 2008

Vimperator

A few days ago on a previous post I posted about how I was getting used to Vim and was liking it. A commenter mentioned Vimperator, which is a Vim-like plugin for Firefox. It basically takes Firefox and gives it a Vim-like interface.

It's pretty good. One may wonder why you would want to use something like this for a web browser, which is something that is inherently a mouse-based application.

If you think about it, what are the main things you do with a web browser? Open URLs, scroll, type text into text areas, and click links. At least that's what I mainly do. What Vimperator does is put most of these into keyboard commands.

For typing a URL, instead of pressing Alt+T (which is what I believe the shortcut was) you push 'o'. It is a much less awkward shortcut. What it does is begin entering the :open command, and then you type what it is you want. It even combines the address field with the search field, so that if you enter something that isn't a web page it sends you to a Google search. It's also nice because it has tab-completion.

For typing things into input boxes or text areas, and for clicking links, you have "hints mode". Press 'f', and it pops up a little number next to all the interactive components on your screen. You then hit the number and it acts as though you clicked the component (to open something in another tab, use 'F' instead). Pretty neat! The only problem with it that I've found is that in GMail half the "links" are actually span tags with onclick attached to them. This confuses Vimperator, as it doesn't realize that they are interactive components and doesn't give them numbers in hints mode. Note that you can still use everything the way you used to.

Finally, scrolling works the way it always has, but you can also use the hjkl shortcuts too to move around the page. Sounds useless, but saves you the effort from moving your hand all the way over to the arrow keys, and then having to move your hand back when you're done scrolling.

My other Firefox plugins like Firebug, Greasemonkey, HTML Validator, they all work as they used to.

It's probably not for everybody, it is a power tool. By default it takes away all the stuff at the top like the back button, menu bar, etc. You can get these back, but it is not the default. I wouldn't recommend it to people who don't want to take the few minutes or so to get used to it. I've had people sit down at my computer when I had Vimperator enabled and had no clue how to type in a URL (just press 'o'). So that's your warning. I like it, but you may not.

UPDATE: I stopped using Vimperator because it makes Firefox very slow. For a while I just thought it was Firefox, but it ended up being Vimperator so I scrapped it.

Sep 28, 2008

JRuby and SQLite

I've heard some fuss about JRuby not supporting SQLite. Personally, this doesn't bother me since I've stuck with MySQL, but some people might be interested. Here's how to get it working (this is for Ubuntu, but I don't think it'd be that different on other systems so long as you know how to edit files and install gems).
jruby -S gem install activerecord-jdbcsqlite3-adapter
This installs the JDBC Sqlite adapter, and should include any dependencies. If it doesn't, you need:
jruby -S gem install jdbc-sqlite3
After that, just edit config/database.yml to use the jdbcsqlite3 adapter instead of the normal one:
development:
adapter: jdbcsqlite3
database: db/development.sqlite3
timeout: 5000
Presto! You're done.

Note that I'm assuming you're using Rails here, if not then you don't need the activerecord gem.

Sep 27, 2008

Ubuntu Game Experiment

On occasion I like to revisit the Linux gaming scene. No, it is not because I like to see horrible failures, rather I've thought of an interesting experiment.

Linux will not catch up to Windows or consoles in terms of hard-core games, at least in the next few years. These games take a lot of manpower to produce, and if the leaders of that manpower do not want to release on Linux, then it won't get released on Linux. Even under wine, the performance sucks a bit - I have Oblivion and Guild Wars working fine under wine right now, but they get a much lower FPS. I'd rather just reboot to Windows and use my graphics card to its full potential (I paid for it didn't I?).

I think too many people are trying to get the hardcore gamers to switch to Linux by making their games work. Personally, I think this is a bad idea. Hardcore gamers are among the biggest bitches I've ever seen, just go on Battle.net or something and listen to them talk. It's retarded. Why would we want these people polluting Ubuntu forums with their crap?

What more focus should be put on is the other 90% of gamers. The ones who like Frozen Bubble or Those Funny Funguloids, and only play once in a while - among this 90% are those people called girls, which last I checked are severely lacking in the Linux world.

Anyway, the moral of my story is that instead of targeting the niche market of hardcore gamers as would-be Linux converts, why not focus on everybody else?

Sep 25, 2008

Rails Fixtures Order

So I've been having some trouble with Rails and fixtures. What I have in my fixtures are two tables, we'll call them t1 and t2. There is also a join table between these two tables, which has some info about the relationship between rows in the two tables.

Now suppose I have n1 fixtures for t1, and n2 fixtures for t2. That means there are O(n1n2) fixtures in the join table, in my case I have an entry for every pair. It would be a huge pain in the ass to enter all that data into the fixture manually. So what I do is just
t1 = Table1.find(:all)
t2 = Table2.find(:all)
t1.each do |r1|
t2.each do |r2|
#output fixture YAML
end
end
There is one problem with this. If the fixtures for Table1 and/or Table2 are not run before the fixture for JoinTable, then you're going to run into problems.

There are two things to do. The first one is in any controller test class, when you put your fixtures thing at the top, you put it like this:
fixtures :table1, :table2
fixtures :join_table
This seems fairly intuitive, but my first intuition was to put it like this:
fixtures :table1, :table2, :join_table
Then I had an epic brain fart trying to figure out why it wasn't working.

The second thing you need to do only needs to be done if you use the db:fixtures:load rake task. What this does is it loads your fixtures into your development database, which is very handy for coding. When you're in the development phase of your app, you don't need to create new migrations for your DB, just edit the old migration, and run db:migrate:reset. Makes things cleaner and easier to follow IMO.

However, this loads things in alphabetical order. You could name all your tables to be in the order that they should be loaded, but this is slightly annoying. The solution is to tweak your environment.rb file. Just add (EDIT: the other one didn't always work for me, I changed this so it does work):
ENV["FIXTURES"] ||= "table1,table2,join_table"
to config/environment.rb, and you will get the correct loading order.

EDIT: Always remember that when you add a new model, you'll need to manually add it to this list or your fixtures for that model will not be loaded. Learned this one the hard way, wondering why the fixtures were being loaded properly for tests, but not for the dev database.

EDIT (again): This doesn't always work, but it seems to work more often than if you didn't put this. The best option would be to load in fixtures, load whatever time-dependent stuff you have manually, and write a small script to export the DB into the YAML fixtures. That's what I ended up having to do finally, and it works like a charm.
Another thing if you don't want to do this is to create another script to do it for you. So instead of doing the normal rake task, you can have a script like this:
`rake db:fixtures:load`

# run whatever tasks you need ...
Run this script with script/runner so that it has access to your Rails models and what-not, and you'll be able to generate data automatically. You'll also have to load your file in from test/test_helper.rb during the setup() method so that your fixtures get loaded properly into tests.

Sep 24, 2008

WEBrick and Authentication

Picture this scenario: You are working on a Rails project. Your team (not just dev people, but any others like marketers, etc.) is distributed, so you're not all in the same office - and hence can't have any sort of internal network. You have a server somewhere for centralizing things via SVN, and you put other tools on it like Trac. That kind of thing is pretty easy, and with Apache you can just throw up some AuthType Basic stuff to keep unwelcomes out.

However, I want to make it so that the development version of the web app is viewable to non-dev people. Now for dev people, it's a requirement that they can get the code onto their machine and use it without relying on the central server to do work. So they have to be able to get MySQL up and running, install Ruby (or in the case of my project, JRuby), and anything else. But for the non-techies, how do they get everything up and running? They're probably running Windows too (it's funny, the entire dev team that I'm working with runs Mac, except me, who runs Ubuntu), which means that installing MySQL and all that will be a pain in the ass.

The first thought is maybe use Glassfish or something to deploy the semi-finished app, and then put some password lock. But that sounds like a lot of work. You need to WAR that shit up, and re-deploy it every time you do an update. Not cool. Why not just use WEBrick, which comes with every Rails project, and is as simple as going 'jruby script/server'?

The problem is when you want to password protect everything. Ideally, we don't want to have to make code changes. We want it so that on our local machines, we don't have to enter a password to see the site.

The first solution was to use Apache for authentication, then proxy over to WEBrick, who's port (3000) is not open to the outside world. This would work in theory, except that mod_proxy gets invoked before any authentication can happen. So even with the auth statements in there, it still just proxies over to WEBrick without asking for anything. Not cool.

Next solution: authenticate, then rewrite. Put in some authentication stuff, then mod_rewrite everything to localhost:3000. Authentication worked, rewrite didn't. I have no idea why. I would put in [P], but that would give a 404. Using anything else would result in a direct rewrite, and would redirect you to your own localhost:3000, which obviously would not give anything unless you had WEBrick running on your local machine (good thing it wasn't, or I would've been mightily confused until I looked at the address bar).

So my final solution was to modify the code. This in itself was a pain in the ass. There are many different ways to use HTTP authentication with rails. Rails has it baked in to use HTTP authentication, but not to use our htpasswd file. This meant that everybody had to have another username and password that was stored with the application just to access this little thing. As a coder, I find this level of duplication revolting, and so I attempt to write a little bit of code to check our htpasswd file to see if it's the right password entered. On Linux, by default, htpasswd uses the system's crypt() function to encrypt thing, which in Ruby translates to System#crypt. It unfortunate takes a salt to encrypt things (well, fortunately for security reasons, unfortunately for me since I didn't know the salt). I couldn't figure out the salt, so that ended up being wasted effort.

Then I found this beautiful thing. It is a plugin for Rails that lets you use an htpasswd file for HTTP authentication. It probably does more than that, but this is exactly what I wanted - well almost, I didn't want to make any code changes, but c'est la vie. It was one line of code:
htpasswd :file => '/path/to/passwords'
Put that in app/controllers/application.rb, and you've got your password locking. Now I can make WEBrick accessible to the world, and only the people with a username/password can see anything. Awesome.

I learned a lot during this adventure, about Apache and Rails Authentication and (rant alert!) how frigging useless #rubyonrails is when you have anything slightly advanced to do. I've spent a fair bit of time in there, and can answer the majority of questions people ask, because for the most part they are asking the questions because they're too lazy to read a good Rails book or google for an answer (which is what I do sometimes when I don't immediately know the answer). Every time I have asked something in there it has been something relatively advanced, and the response is either "figure it out for yourself", or silence. The first is a reasonable enough answer, given the standard questions that get asked in there, but not entirely helpful...what do they think I've spent the last hour or so trying to do? Silence is ok too, since if you don't know the answer then you're not expected to say anything. But still, both results are pretty useless.

What is still on the table: How to get WEBrick to run as a daemon with JRuby. The JRuby implementation has disabled the use of fork(), so using the -d flag for WEBrick is not an option. I'll have to write a daemon script or something.

Sep 22, 2008

Vim, revisited

A few months ago (just over 3 in fact) I posted about having begun to learn vi1. Since then, I've learned a lot about it, discovered several plugins, and many times attempt to hit Esc after typing into Firefox. Or use hjkl to navigate in a text area. The only other program I now use to edit text is OpenOffice, mainly because it's a little difficult to get fancy charts and things into Vim. Also I submitted a paper in monospaced font with no formatting, the prof might be a little annoyed. You might think it overkill to use Vim for something simple like jotting down notes, but the funny thing is that Vim starts a fair bit faster than any other graphical text editor on my machine, like GEdit or Kate.

I've replaced my IDEs with it. I used to use Quanta, but it is slow to boot, and is once in a while unstable. Once in a while it will crash when I use the built-in FTP. And when I mean crash, it not only crashes Quanta, but the entire X server goes down. Slightly annoying.

Your productivity is improved by a fair bit when you start using this. Due to the mode-based editing, it is much easier to type commands than using Ctrl/Shift/Alt/some-combination-of-the-three, especially when you want more complex things. Want to delete a line? Press dd. Swap two characters? xp. One I use a lot is Ctrl+6 (or Ctrl+^ without pressing Shift), which opens the last file you had open. Kinda like how in Half-life you press q to get to the last weapon. On that note, I wonder how games would play if you could differentiate between q and Q... I guess you wouldn't be able to use Shift for sprint anymore.

You can even record a set of keystrokes, and bind that set of keystrokes to a key: press q, then the key, call it k. Every key you type will be recorded. Then press q to stop recording. Then later on when you want to use that recording, press @ then k. My only problem with this is that @ is a little awkward to do over and over, but there is probably a rebinding of keys.

It doesn't just end with the keyboard shortcuts. There are plenty of plugins for Vim. I have three favourites:
- VTreeExplore - it is a window in Vim (btw in Vim you can split windows, just like most fancy editors) that shows a directory tree. Very handy. Others have written about it too.
- Surround - when typing contexts (like dw or d$, which are delete word and delete from-cursor-to-end-of-line, respectively) you now can use s, which affects the surroundings around a bit of text. Type ds( to delete the parentheses around something. Type cs{[ to switch the curly brackets to square brackets.
- Vim's Rails plugin - This does more than just syntax highlighting. It adds some very helpful things for file navigation (something that is a fair bit annoying in Vim). If your cursor is over a model or controller name, you can press gf to go to that file. If you're in a view or model, press :Rcontroller (this uses tab auto-completion too, so just type :Rcont and hit tab) to jump to the controller. Similarily for jumping to models. If you're in a controller action, you can jump to the view. It's all pretty handy, and there are probably plenty of shortcuts that I don't know about. You can read here to learn more about Vim+Rails.
Note: I know at least one person is going to mention Textmate. Two things: I don't use a Mac (nor do I intend to any time soon), and I don't like to pay for software.

So it's been over 3 months and I'm not turning back. In fact, this was pretty much the case after a few weeks, and I am continually learning more. I recommend it to any programmer. You can also try Emacs too, I think it does the same kind of stuff and it is mostly a matter of preference - kinda like Ruby vs. Python ;).

1 Technically, it's GVim, which is the graphical version of Vim, which is an open-source remake of an older text editor called vi, but these are just details.