Archive for October, 2009

Size != Count

Friday, October 30th, 2009

When using a has_many :through in Rails with a counter_cache an interesting thing can occur. When you call size on the association, it can return a seemingly incorrect number. This is caused by the following code in activerecord/lib/has_many_through_association.rb:

def size
  return @owner.send(:read_attribute, cached_counter_attribute_name) if has_cached_counter?
  return @target.size if loaded?
  return count
end

It’ll reach the counter_cache column which could be incorrect, giving you all the objects returned when you look up the association, but an invalid number. This was only in my tests where data was being created through Machinist. Just watch yourself for this, this is the second time it has caught me, and ideally the last.

Connecting to Multiple Databases Using ActiveRecord

Saturday, October 17th, 2009

You can call establish_connection with the key that points to another database config in your config/database.yml file

class Person < ActiveRecord::Base
  establish_connection(:hr)
end
class Ticket < ActiveRecord::Base
  establish_connection(:bug_tracker)
end

If you have a whole bunch of models that need to connect to another database:

class HR < ActiveRecord::Base
  establish_connection(:hr)
end

class People < HR
  # ...
end

class Resource < HR
  # ...
end

Fixed By Rails 3

Friday, October 9th, 2009

Today I launched a sister site to fixedbytm2.com which is fixedbyrails3.com. Here you can list your gripes and wishes for Rails 3, as well as the new feature of being able to vote on them! Enjoy!

Banning Users Using Middleware

Tuesday, October 6th, 2009

Bo Jeanes, a coworker at Mocra, recently implemented a way to ban people on one of his side projects DearQUT because somebody was posting nasty messages. We were talking earlier today about it and the topic of using a middleware came up since we “don’t want to waste resources on that asshole”. So I thought I’d investigate to to see how easy it is to make a middleware in Rails, turns out it’s very easy!. If you don’t like reading blog posts, I have sample Rails application containing the very same source code I used for this blog post. This contains also the “Special Github” extras like an admin section for adding/editing/deleting banned IPs! I also “cheated” by stealing elements from the Railscast on Rack Middleware.

The Ban Hammer

First off I generated a model called BannedIP by running script/generate model BannedIP ip:string and ran rake db:migrate to create the database and the banned_ips table.

After that, I made a file called lib/hammer.rb and it goes a little like:

class Hammer
  def initialize(app)
    @app = app
  end
  
  def call(env)
    if BannedIP.find_by_ip(env["REMOTE_ADDR"])
      file = "#{RAILS_ROOT}/public/banned.html"
      [403, {"Content-Type" => "text/html" }, [File.read(file)]]
    else
      @status, @headers, @response = @app.call(env)
      [@status, @headers, self]
    end
  end
  
  def each(&block)
    @response.each(&block)
  end
end

Eagle-eyes will see that this is almost a blatant rip-off of Ryan Bates’ code. Ignore that part. Admire that I call BannedIP.findbyip(env["REMOTE_ADDR"]) which will return an BannedIP object if one exists, otherwise it’ll return nil. in the case that someone’s banned then it’ll show them a very lightweight page with “You have been banned from this site.” and they’ll feel guilty and stuff (this feature actually coming in v2).

Now to use this middleware you have to add config.middleware.use ‘Hammer’ to your config/environment.rb file and (of course) restart the server. Every request will of course query the database once more which, if you’re running a large big HUGE site can lead to performance issues.

Of course you could just use iptables and do something like iptables -I INPUT -s 25.55.55.55 -j DROP, but then they won’t be told why they’re banned.

Construct

Thursday, October 1st, 2009

Over the past month or so I’ve learned to dislike Integrity for all it’s quirks. Whilst it’s a fabulous piece of software in theory the bugs (“notifyofbuild” fails, attempting to press “rebuild” attempts to go to a page that doesn’t exist, etc.) and it’s single threadedness has driven myself (and others) up the wall.

Last Tuesday I was in The Zone, and coded Construct effectively that night. It was as functional as integrity and didn’t hang when there was a build in progress! It works by running on port 80 and uses Github’s & Codebase’s post-receive hooks (you’ll have to set them up yourself I’m afraid).

So go try it out for yourself! Interested in your feedback for it.