count_on counter_cache

Posted over 7 years back at zerosum dirt(nap) - Home

Counter cache is my new friend. It’s a very important little feature available on ActiveRecord that makes counting associations efficient by maintaining a cache on the model.

Although it’s documented in AWDWR (p359 in my shiny new copy of the second edition), I guess it slipped my mind until now, so I thought I’d blog about it just in case anyone else was looking for a solution…

So why does it rock so hard, you ask? Let’s say that I’m building YADRC (Yet Another Digg/Reddit Clone). I need to count the votes that users make to determine the popularity of an article, display that number, and use it to rank the order of the stories. So we set up our models: a story model, a vote model, and a user model, and we create the appropriate associations. Our vote.rb is going to look something like this:

class Vote < ActiveRecord::Base
  belongs_to :user
  belongs_to :story
end

Predictably, Story has_many votes and User has_many votes. Now we can do something like this to find the number of votes on a story object:

Story.find(4).votes.size

This will work nicely right out of the box. However, once we have a significant amount of stories logged in our system and a reasonable number of votes on each story, performance goes straight to poop. The reason is that each time we’re generating a score for a story (and remember, we’ve got N stories), we’re running a query like this against our database:

SELECT count(*) AS count_all FROM votes WHERE (votes.story_id = 4) 

If we have any real amount of data in our system, this is going to get really ugly. Counter caching is one way to help counteract this problem. Let’s rewrite our model to use it:

class Vote < ActiveRecord::Base
  belongs_to :user
  belongs_to :story, :counter_cache => true
end

We also have to add a column, called votes_count, to the stories table in our database. Make sure to specify a default value of 0 in your DDL. Then we generate a migration, run it, and now we’re ready to try again. The difference should be pretty dramatic. If we tail -f our development log, we’ll notice that those count(*) queries aren’t getting run anymore. So what’s happening?

ActiveRecord is using our counter cache column (called votes_count in this case) on the stories table to store the number of belonging objects on the associate class. This value is incremented when an object of this class is created, and decremented when it’s destroyed. The result is that we have a local “cached count” on the Story instance so we don’t have to constantly query the votes table directly. Good deal, eh?

There are two additional things worth noting about counter caching. As Dave Thomas points out in AWDWR, the counter won’t get updated if entries are added by setting the link to the parent directly in the child like this:

vote = Vote.new
vote.story = story
vote.save

If you’re doing it this way, you’ll have to force the parent class to refresh the collection. The right approach is to add a Vote through the Story object, which makes the parent aware of the increment (or decrement) and update the counter cache accordingly:

story.vote.create

The other point I wanted to make was that if you call the count method on object instead of using size, it will always run the actual count query on the underlying database, instead of using our cached shortcut. Thanks for the tip on that one, technoweenie.

Parallels Makes IE Testing Suck Less, Melts Power Cord

Posted over 7 years back at Ryan Tomayko's Writings

For the most part, the Mac has been an insanely productive environment for web development. The 1GB MacBook Pro stays snappy even when running three or four Ruby VMs loaded with beefy Rails apps, a local PostgreSQL database, many Vims, a couple Terminals, Firefox (with many tabs), The Gimp, and iTunes. I've been spending something on the order of 80 hours/week in this world for some time now and there’s just not a whole lot of pain to report on.

I get a little paranoid when stuff Just Works though so it’s a good thing 99.9% of our customers run Internet Explorer. I'm pretty hard on IE but I will admit to at least one thing it does really well: destroying any sense of pleasantness a developer may feel when building web applications.

We like to test on three different versions of IE:

  1. A fully patched IE 6.0 on a fully patched XP SP2.
  2. The stock IE 6.0 that comes off the original (pre-SP2) XP install media with no patches.
  3. A fully patched IE 7.0 on a fully patched XP SP2.

Of course, you can’t do anything silly like run multiple versions of IE on a single machine. Before IE 7.0, we had two machines (that’s actual physical machines) acting as Terminal Servers for each of the IE 6.0 versions. This sucks for the obvious reasons but adds another soul eating component to the mix: Microsoft’s Remote Desktop Connection for Mac.

  • Slow (still compiled for PPC).
  • Buggy horribly flaky mess of crap hasn’t been updated in years.
  • Cannot start more than one session at a time making it impossible to quickly switch between the IEs.

Once IE 7.0 became a reality, we decided to pony up for Parallels. Unplugging the two Windows boxes instead of adding another one more than paid for the Parallels license but the switch didn’t really solve the productivity problems since you still have to fire up a resource hungry VM for each IE.

IEs Running In The Dock

The latest Parallels beta’s Coherence Mode is trying really hard to bring something of a Mac native feel to Windows apps running under the VM (watch a screencast). Here we have IE 6.0 and IE 7.0 running in the Dock next to Safari and Firefox (kind of grosses you out at first).

You can drag those guys over to make them persistent Dock items. Launching from the Dock will start the VM, enter Coherence Mode, and start a new instance. You can also use QuickSilver:

Quicksilver and the IEs

That’s the good news. The bad news is that after about ten minutes of running with both VMs open, I started to smell burning electronics. The MacBook didn’t seem to be running any hotter than normal and I didn’t see any smoke so I figured maybe it was unrelated. When I went to pack up and go home for the day, I noticed that about ½" of the power cord had melted away, leaving the bare wire exposed!

Melted Power Cord

Taking every precaution, I quickly “fixed” the issue using a pair of paper scissors and black duct tape.

The 85W MagSafe Power Adapter product page has a ton of negative reviews mentioning the “melting thing” and Apple technicians have allegedly said the cause is a hardware issue that causes the laptop to draw too much power. Whatever.

EDIT: apparently, that last paragraph did not do a very good job of relaying my discontent with the melting power cord issue. To be clear: power cords should not melt, even when running beta software. This is clearly an Apple issue.

Tinkering around with the Parallels VM configuration seems to help a bit. I tried to create the lightest VM for running IEs as possible. Here’s a few tips that seem to be helping:

  1. Remove sound, floppy, CD/DVD, and USB from the Parallels configuration.
  2. Under Options / Advanced set the Cache Policy to Mac OS X.
  3. Under Memory, set Main Memory way low (I have mine at 96MB) and adjust the Video Memory to your maximum screen resolution (I have mine at 8MB).
  4. In Windows, disable as many services as possible. Things like Windows Update, the bullshit firewall, sound, the theme engine, etc.

These have not been rigorously tested but everything seems to be running much more smoothly on a 1GB MacBook Pro after an hour or so. Slapping another GB of RAM in here would probably make things a lot smoother as well but I just can’t get over the idea of having to double my RAM just to run a couple of IEs.

All in all, Parallels makes IE suck a bit less on the Mac but this is still a horrible broken mess. What are you guys doing about the IE problem?

Status

Posted over 7 years back at The Hobo Blog

Hobo is currently beta quality. Although Hobo is in active use in production applications, please be aware that if you choose to deploy a Hobo/Rails application on the Internet you do so at your own risk.

Also note that at this stage we reserve the right to make breaking changes to the API.

Current version: 0.8.3

Known Issues

Aspects of Hobo we need to work on:

(of course there’s much more to be worked on than mentioned here – if you come across anything you think should be included in this heads-up, please let us know in the forums)

Active Record Support

Hobo does not currently support has_one and has_and_belongs_to_many. Of course it’s all just Rails so you’re free to use those features in your application, but you will probably run into problems if you try to use Hobo’s various features in conjunction with those kinds of associations. has_one is definitely on the to-do list. has_and_belongs_to_many is not – use has_many :through instead, it’s much better. If you think we’re wrong about this, let us know in the forums! You won’t be the first, but so far we’re sticking to our guns.

DRYML Syntax and Naming

With the 0.6 and 0.7 releases we’ve now done our big cleanup of DRYML syntax and naming. However you can still expect small changes from time to time that will require you to update your apps.

DRYML Performance

Because DRYML promotes a very high level of code re-use in the views, a DRYML page tends to include far more method calls than a typical ERB template. On big pages this can be a significant performance issue.

Tag calls are currently slower than they need to be because at this stage we’re optimising for code clarity rather than performance. At some point we will start tuning this code to run faster, or…

Status

Posted over 7 years back at The Hobo Blog

Hobo is currently beta quality. Although Hobo is in active use in production applications, please be aware that if you choose to deploy a Hobo/Rails application on the Internet you do so at your own risk.

Also note that at this stage we reserve the right to make breaking changes to the API.

Current version: 0.8.3

Known Issues

Aspects of Hobo we need to work on:

(of course there’s much more to be worked on than mentioned here – if you come across anything you think should be included in this heads-up, please let us know in the forums)

Active Record Support

Hobo does not currently support has_one and has_and_belongs_to_many. Of course it’s all just Rails so you’re free to use those features in your application, but you will probably run into problems if you try to use Hobo’s various features in conjunction with those kinds of associations. has_one is definitely on the to-do list. has_and_belongs_to_many is not – use has_many :through instead, it’s much better. If you think we’re wrong about this, let us know in the forums! You won’t be the first, but so far we’re sticking to our guns.

DRYML Syntax and Naming

With the 0.6 and 0.7 releases we’ve now done our big cleanup of DRYML syntax and naming. However you can still expect small changes from time to time that will require you to update your apps.

DRYML Performance

Because DRYML promotes a very high level of code re-use in the views, a DRYML page tends to include far more method calls than a typical ERB template. On big pages this can be a significant performance issue.

Tag calls are currently slower than they need to be because at this stage we’re optimising for code clarity rather than performance. At some point we will start tuning this code to run faster, or…

Demos

Posted over 7 years back at The Hobo Blog

Download complete Hobo demo applications, and watch them being created in the screencasts. All the demos require Rails 1.2

The demos are standard Rails apps. To run them

  • Download and unpack the demo archive

  • Create the database, e.g.

    $ mysqladmin create pod_development

    (look in config/database.yml for the name of the database you need to create)

  • To create the required tables, open a terminal in the demo’s main directory, and:

    $ rake db:migrate

  • Run the development server

    $ ruby script/server

  • Point your browser at http://localhost:3000

POD Demo

POD is a simple classified advertising application, created using Hobo and Rails in just five minutes.

* You can watch the the development of POD via the screencasts page

Downloads:

* Pod Demo - Introduction to Hobo: zip * Pod Demo - Page Customisation: zip * Pod Demo - Replacing the Theme: zip

(Note that the third demo (stylevantage) is massively incomplete and broken in many places. It is included just for information purposes)

To-Do List Demo

No screencast, but some discussion of the permissions in this post

* Download ToDo: zip

Demos

Posted over 7 years back at The Hobo Blog

Download complete Hobo demo applications, and watch them being created in the screencasts. All the demos require Rails 1.2

The demos are standard Rails apps. To run them

  • Download and unpack the demo archive

  • Create the database, e.g.

    $ mysqladmin create pod_development

    (look in config/database.yml for the name of the database you need to create)

  • To create the required tables, open a terminal in the demo’s main directory, and:

    $ rake db:migrate

  • Run the development server

    $ ruby script/server

  • Point your browser at http://localhost:3000

POD Demo

POD is a simple classified advertising application, created using Hobo and Rails in just five minutes.

* You can watch the the development of POD via the screencasts page

Downloads:

* Pod Demo - Introduction to Hobo: zip * Pod Demo - Page Customisation: zip * Pod Demo - Replacing the Theme: zip

(Note that the third demo (stylevantage) is massively incomplete and broken in many places. It is included just for information purposes)

To-Do List Demo

No screencast, but some discussion of the permissions in this post

* Download ToDo: zip

Hobo Released!

Posted over 7 years back at The Hobo Blog

And there’s even a screencast :-) This is an early beta - version 0.4.0 You are NOT recommended to use this in an application on the open Internet. You are strongly recommended to play around with it!

* Watch the Hobo screencast (10 minutes)

What is Hobo?

* Hobo extends Rails is a number of ways, to let you build full blown web applications very quickly and easily.

* Hobo lets you add dynamic Ajax interfaces to your application with no extra programming.

* Hobo gives your application switchable themes, so you can have an elegant design right out of the box.

Who is it for?

* Hobo can speed up the creation of rich, complex web applications as well as simple internal apps and rapid prototypes.

* Hobo is a great way for newcomers to Ruby on Rails to learn and practice agile, iterative application development.

Getting Hobo

Note Hobo requires Rails 1.2 RC1, which you can install like this:

gem install rails --source http://gems.rubyonrails.org -y

You should read the status page before downloading Hobo.

Hobo is distributed in two forms, a gem and a plugin (svn repo).

Hobo Gem

The gem is ideal for trying out Hobo with a new app. It gives you a single command:

$ hobo <app-name>

It works just like the rails command, creating a blank Rails application pre-configured for Hobo. First download the gem:

* hobo-0.4.0.gem

Then:

$ gem install hobo-0.4.0.gem

(Sorry folks we’ve not got our Rubyforge stuff together as yet)

Hobo plugin

If you want to add Hobo to an existing application, first do:

$ ./script/plugin install svn://hobocentral.net/hobo/trunk
$ ./script/generate hobo

Then there are a few optional steps, depending on which Hobo features you’re after. In the screencast you’ve seen:

Hobo Rapid and the default theme:

$ ./script/generate hobo_rapid

Hobo’s user model:

$ ./script/generate hobo_model user
$ ./script/generate hobo_front_controller front

More documentation will follow!

Hobo is distributed under the terms of the MIT licesne.

Hobo Released!

Posted over 7 years back at The Hobo Blog

And there’s even a screencast :-) This is an early beta - version 0.4.0 You are NOT recommended to use this in an application on the open Internet. You are strongly recommended to play around with it!

* Watch the Hobo screencast (10 minutes)

What is Hobo?

* Hobo extends Rails is a number of ways, to let you build full blown web applications very quickly and easily.

* Hobo lets you add dynamic Ajax interfaces to your application with no extra programming.

* Hobo gives your application switchable themes, so you can have an elegant design right out of the box.

Who is it for?

* Hobo can speed up the creation of rich, complex web applications as well as simple internal apps and rapid prototypes.

* Hobo is a great way for newcomers to Ruby on Rails to learn and practice agile, iterative application development.

Getting Hobo

Note Hobo requires Rails 1.2 RC1, which you can install like this:

gem install rails --source http://gems.rubyonrails.org -y

You should read the status page before downloading Hobo.

Hobo is distributed in two forms, a gem and a plugin (svn repo).

Hobo Gem

The gem is ideal for trying out Hobo with a new app. It gives you a single command:

$ hobo <app-name>

It works just like the rails command, creating a blank Rails application pre-configured for Hobo. First download the gem:

* hobo-0.4.0.gem

Then:

$ gem install hobo-0.4.0.gem

(Sorry folks we’ve not got our Rubyforge stuff together as yet)

Hobo plugin

If you want to add Hobo to an existing application, first do:

$ ./script/plugin install svn://hobocentral.net/hobo/trunk
$ ./script/generate hobo

Then there are a few optional steps, depending on which Hobo features you’re after. In the screencast you’ve seen:

Hobo Rapid and the default theme:

$ ./script/generate hobo_rapid

Hobo’s user model:

$ ./script/generate hobo_model user
$ ./script/generate hobo_front_controller front

More documentation will follow!

Hobo is distributed under the terms of the MIT licesne.

The Quest For The Perfect RoR IDE...

Posted over 7 years back at zerosum dirt(nap) - Home

Ruby itself doesn’t directly support multiple inheritance (yay for mixins) but the community sort of does. If you survey a random group of RoR developers, about half of them seem to come from a structured (oftentimes strongly-typed) OO language like Java, and the other half comes from the scripting world. One of the best things about Ruby is that it appeals equally to both camps. It’s a common ground of sorts, a compromise, maybe the best of both worlds. I dig that.

But as everyone knows, different backgrounds beget different toolsets. In the case of Ruby on Rails, it raises the question: do we need a real IDE for this kind of work, or is a simple text editor good enough?

I’ve gravitated back and forth between the two coding camps over the years. It’s a “right tool for the task” sort of thing if you ask me. You want a lightweight project management application that runs on the web? PHP please. You want a robust scalable service for the delivery of digital media and have some money to spend? Let’s do that one in Java. There’s a religious war to be had here for sure, and I don’t want to get into that… The interesting thing (and the point I’m trying to make) is that the tools you come to use and respond to differ depending on that background.

When I’m working in PHP, I use vim. No, really. I tried PHPEclipse and the pluses just didn’t outweight the minuses for me. I also tried Komodo. I’m an old school vi hacker, and I do all my sysadmin work in vi, so it became the natural choice. I don’t regret it. Well, not often, anyway. After all, PHP is a scripting language, right?

When I’m working in Java, I’m spoiled to death by IntelliJ. Yes, it’s expensive. Yes, there’s a learning curve. And yes, it’s worth every damn penny/hour spent. I’ve tried Eclipse. And it’s alright, but it’s not IDJ. The JetBrains guys have delivered what is by far the most intelligent, usable IDE I’ve ever used. That’s my story, and I’m sticking to it.

So is Ruby a scripting language, or is Ruby a proper OO “enterprisey” language? I’d argue that it’s both and that it’s use dictates the classification. But when you’re building Rails apps, you’re firmly entrenched in OO/MVC proper webapp territory, and therefore, imho, that demands the use of a proper IDE. Particularly once a project becomes sufficiently large.

So what do I use when it comes to Rails work then? Well, up until now I’ve been using RadRails with RDT and Eclipse. It works pretty well for the most part. But it’s no IntelliJ. We don’t, of course, have auto-complete yet, but the syntax highlighting is getting there, the generators and rake tasks are wrapped up nicely, as is run output, test execution, etc etc. It’s better, for me, than using vi, by leaps and bounds and it seems to be getting better and better (nice job guys!).

RadRails seems to be the choice for Windows and Linux users, but everyone else I know on OS X seems to be using TextMate. Whoah, what? I’ve never used TextMate — am I missing out? But wait, TextMate is just a text editor right? It’s NOT an IDE and doesn’t aspire to be. Regardless, the popular opinion seems to be that it’s “good enough”.

So what do you use? Are you, like everyone else out there, a TextMate-phile? If so, why? Don’t get me wrong, I understand the allure of a minimalistic text editor for hacking script, but have you been spoiled by something as nice as IDJ in the past? Oh man would I kill for ctrl-space to autocomplete/interrogate an object to discover it’s methods..

I wonder if there are a lot of people who have come over from the Java side of things who have switched to TextMate, particularly people who have used IntelliJ in the past. Am I making a blanket assumption that most of the people using text editors to hack Rails are not Java converts? Am I just overcomplicating the whole thing? Is TextMate really “good enough”?

The entire Rails core team purportedly uses TextMate… Maybe I’m just missing something? I’d love to hear your opinions.

UPDATE: I’m using NetBeans now. And it’s great.

IntelliJ On Rails

Posted over 7 years back at zerosum dirt(nap) - Home

If you’re an IntelliJ user like me, and have recently been bitten by the RoR bug, you’ll be glad to know that there’s a plugin on the way. It’s still in it’s infancy, lacking a lot of features, and is therefore not in the repository, but that doesn’t mean we can’t play around with it. What follows is a brief tutorial on how to locate, install, and use the ruby plugin…

First you need to check out the sources from the Subversion repo:

svn co http://svn.jetbrains.org/idea/Trunk/ruby

Use Ant to build it (run ant from the directory you co’d to, where the build.xml file lives). The build process should generate a jar file in dist/ called ruby-SNAPSHOT.jar.

Next, make a new directory in your IDJ plugins directory called ‘ruby’ and make a lib directory in there. Copy the jar to $IDJ_ROOT/plugins/ruby/lib. On OS X, this path is something like /Applications/IntelliJ IDEA 6.0.2.app/plugins/ruby/lib/.

Start IntelliJ. Go to Settings → Project Settiings → Project Structure. In Global Resources, under JDKs, right click and add a Ruby SDK. On OS X, you’ll want to point it at /usr/local, or whereever your copy of Ruby has been installed.

Now you should be able to create a new project and select Ruby SDK from the JDK list (heh). Create a single module project, select Rails as your module type, and set the Ruby SDK for the module. Finally, you’ll be given the chance to generate a new Rails application skeleton, generate missing files, or use an existing Rails app. Go ahead and create a test project and generate a new Rails framework. I’ll do all the work for you and populate the project explorer with that oh-so-familiar directory structure. Check out that ugly Ruby icon they’re using. Jeeze, what is that?

Right click in the project explorer and select New → Controller. Name your controller test and add an action name hello. Click OK. IDJ will run the Rails generator and update the project explorer. You now have a TestController with a hello action, the corresponding view template, and the expected test stubs.

You can select Run → Run… to start a WEBrick server and test your app. There are some bugs here. First of all, there is no run output in the console view where you’d expect it to be. No web browser is launched, no indication is given of what port number the server gets bound to. Worse, you can’t seem to kill a running WEBrick server without killing the process from a terminal. So yeah, there’s obviously still some work to do here. For now, I’d suggest running WEBrick from the command line (RadRails still wins here, at least). No command completion or real debugging support is available yet either, but hey.. it’s a start. It’s functional, you can run tests from within the IDE, you get basic code formatting, syntax highlighting, etc.

For more information, check out the JetBrains Project Homepage for the ruby plugin, where you’ll find a link to the roadmap and discussion groups. You’ll note that there are plans for autocompletion, ability to browse to symbol, proper YAML, RXML support, etc. I really hope that development continues on this. IDJ is much-loved amongst the Java community, and could be a huge hit in the Rails community if they get a slick, fully functional plugin out there.

Develop with pleasure ;-).

Relief

Posted over 7 years back at zerosum dirt(nap) - Home

So we just finished wrapping up work on the app we’ve been building for the past 8 months. Yay! It’s part of a suite of web-powered tools for a certain niche video editing system. Implemented in Java, leveraging Swing, Axis, WebObjects… Great project and totally learned a lot, but sure am relieved to have delivered it. I’m sure there’ll be a tweak to make here or there, but you know… It’s delivered (rc).

What’s next? Well, I’m not entirely sure to be honest. For the first time in my life I’m thinking about abandoning paid work in order to invest a couple solid months of full-time effort working on the Ruby/Rails app that’s in my head. Perhaps it’s finally time to put my neck out there a little and make it happen. After all, I isn’t getting any younger, now is I?

Fun with IIS : Unexpected Error 0x8ffe2740 Occurred

Posted over 7 years back at Eric Goodwin

I installed IIS on my computer the other day because I'm doing some work for a client who is using ASP. When I tried to start up the server, I got this error message 'Unexpected Error 0x8ffe2740 Occurred'. Having no idea what error 0x8ffe2740 was I hit up google for some answers. Turns out Error 0x8ffe2740 means Port already in use. It would have been nice if they had just supplied a simple explanation in there error message. Is that too much to ask for?

Fun with IIS : Unexpected Error 0x8ffe2740 Occurred

Posted over 7 years back at Eric Goodwin

I installed IIS on my computer the other day because I'm doing some work for a client who is using ASP. When I tried to start up the server, I got this error message 'Unexpected Error 0x8ffe2740 Occurred'. Having no idea what error 0x8ffe2740 was I hit up google for some answers. Turns out Error 0x8ffe2740 means Port already in use. It would have been nice if they had just supplied a simple explanation in there error message. Is that too much to ask for?

Nice Experience !!

Posted over 7 years back at Ajax on Rails


My first Barcamp was really a nice experience. Enjoyed some interesting sessions and some of them were riling me out.
But in all i can say it was good to be there and i will try to attend the all of them in the future.

Searchable RoR Docs

Posted over 7 years back at zerosum dirt(nap) - Home

One of the great things about PHP isn’t the documentation, per se, but rather the centralized, searchable docs interface at PHP.net. Big thanks to Jeremy Durham for putting together an equivalent Rails resource site. There’s obviously still a good bit of work to do before docs are as complete and usable as they could be, but an online searchable repository like this is definitely a step in the right direction. Bookmark it, and add some example code and comments mang.

Oh and while we’re talking about documentation (or lack thereof), don’t forget to donate to the Rails API docs project at Caboo.se if you haven’t already.