RudyGems

Matthew Rudy Jacobs
see me swim
Github
see some of my code
WorkingWithRails
see me working with rails

setting up a simple git server

On the internet you’ll see people talking about Gitosis, or just giving over all of their git requirements to github.

Github is great, but if you just want to do a small personal project, with an off-site repository, go set up your VPS as your main git server.

Here’s how you do it.

  1. create a “git” user

    sudo adduser git
  2. add your ssh keys to that user

    ssh-copy-id git@my.com
  3. create a “bare” repository on your server

    mkdir myRepo.git
    git --bare init
  4. add this as a remote source

    git remote add origin git@my.com:myRepo.git
    git push origin master

BOOM! that is literally all it takes!

Thanks to CommonThread for his tutorial on doing this.

Comments (View)

Rails + Rack Middleware

Rails just released Metal!

Giving us a great framework to build custom Rack processors alongside our application.

Check out this great article over at Soylent Foo.

Recently we had a problem where Microsoft Office was somehow issuing OPTIONS request to our site.

This was blowing up our RESTful controllers that weren’t invited to the OPTIONS party.

We played with Apache rewrites based on REQUEST_METHOD,

but ultimately, we wasted a lot of time fighting against Rails and routing exceptions, blahblahblah.

But now Rails is running off Rack we can deal with it the correct way.

class OptionsCatcher < Rails::Rack::Metal
  def call(env)
    if env["REQUEST_METHOD"] =~ /OPTIONS/i
      [403, {"Content-Type" => "text/html"}, "OPTIONS requests are forbidden"]
    else
      super
    end
  end
end

B00M!

Now this is technically just middleware, and should be declared with a

config.middleware.use OptionsCatcher

and in lib/options_catcher.rb

class OptionsMiddleware
  def initialize(app)
    @app = app
  end
  
  def call(env)
    if env["REQUEST_METHOD"] =~ /OPTIONS/i
      [403, {"Content-Type" => "text/html"}, "OPTIONS requests are forbidden"]
    else
      @app.call(env)
    end
  end
end

but doing it as a Metal makes sense, and is easier than remembering the structure of middleware each time

But there seems to be a problem at the moment with this.

Will try and get a proper Metal working shortly.

Comments (View)

has_one_accessor

HasOneAccessor is a plugin for ActiveRecord that solves the problem of having associations that act like a attribute.

Perhaps only a few users have an openid, so it doesn’t make sense to add an :open_id_url column to your :users table.

Instead you create a new model OpenId

class OpenId < ActiveRecord::Base
  belong_to :user
end

class User < ActiveRecord::Base
  has_one :open_id

  def open_id_url
    self.open_id && self.open_id.url
  end

  def open_id_url=(value)
    if value.blank?
      self.open_id && self.open_id = nil
    else
      self.open_id || self.build_open_id
      self.open_id.url = value
    end
  end
end

Now, that’s not too bad. But maybe you didn’t have time to clean it up.

Maybe you deal with it in your controller.

def update
  if params[:open_id_url] && params[:open_id_url].present?
    @user.open_id || @user.build_open_id
    @user.open_id.url = params[:open_id_url]
  end
  ...
end

Now, that’s all fine.

But we all want to make these things easier.

We all want to cast as much code aside.

ConventionOverConfiguration and all that.

Enter has_one_accessor

class OpenId < ActiveRecord::Base
  belong_to :user
end

class User < ActiveRecord::Base
  has_one :open_id
  has_one_accessor :open_id, :url, :allow_blank => false
end

This takes away all the code,

This takes care of building a record if there wasn’t one, of only saving it when you save the User.

It even kills the association if the value is :blank? (if you pass in :allow_blank => false).

B00m, h34dsh0t?

Comments (View)

SolrQuery - build your solr queries dynamically in Ruby

I’ve been using ActsAsSolr for about 6 months.

And at work I developed some code to make SOLR queries work a bit like the conditions in ActiveRecord.

Check out my library at Github. http://github.com/matthewrudy/solr_query

SolrQuery.build(:keyword => "Feather duster"
=> "feather duster"
SolrQuery.build(:keyword => "clean",
                :organisation => [organisation1, organisation2])
=> "clean AND organisation:(275 OR 6534)"

Wicked!

Check out the readme for more examples.

Comments (View)

UID problems across a shared mount?

We just moved to new Ubuntu servers.

We use file-column (with some modifications) to deal with our file uploads.

deploy@jgp-web01:/var/www/oursite$ ls -l public/uploaded_file/file_name/000/000/051/585/ 
total 4
-rw-r--r-- 1 gerhard www-data 2670 2008-11-15 05:09 MatthewJacobsCV.txt

deploy@jgp-web02:/var/www/oursite$ ls -l public/uploaded_file/file_name/000/000/051/585/
total 4
-rw-r--r-- 1 deploy www-data 2670 2008-11-15 05:09 MatthewJacobsCV.txt

If you look carefully, you’ll see one is owned by “deploy” and the other by “gerhard”.

These are mounted by NFS, shared across the two computers.

So these are actually the same file, but with different permissions on each.

A quick use of the “id” command confirmed this;

deploy@jgp-web01:~$ id deploy
uid=1004(deploy) gid=33(www-data) groups=33(www-data),1005(aspire)

deploy@jgp-web02:~$ id deploy
uid=1002(deploy) gid=33(www-data) groups=33(www-data),1003(aspire)

The answer is;

root@jgp-web01:~# usermod -u 10000 deploy

root@jgp-web02:~# usermod -u 10000 deploy

boom!

Now this is resolved, but you’ll have to chown all the existing files, back to `deploy`, else they’ll still be attached to the old uid.

Comments (View)
svn switch —relocate svn://oldserver svn+ssh://newserver need to move your svn repository?
Comments (View)
Welcome home DHH!
After a long time, it seems DHH is back, actively commiting to rails.
Getting ready for 2.2 to be released, he&#8217;s committed 20 times in the past week.
It&#8217;s nice to see.

Welcome home DHH!

After a long time, it seems DHH is back, actively commiting to rails.

Getting ready for 2.2 to be released, he’s committed 20 times in the past week.

It’s nice to see.

Comments (View)

Google App Engine to support Ruby?

A recent post on the Google App Engine blog refers to;

“Support for a new runtime language”

That’s got to be ruby…

Imagine a bespoke Sinatra-style minimal framework, with DataMapper bindings to the Google DataStore.

No doubt it’ll be pretty quick to make it work with Merb as well.

AWESOME.

Why did google never reply to my job application asking to work on it?

(if you haven’t seen the videos from last years Google IO, then they’re well worth watching - here)

Comments (View)

it’s hard enough to push out a great idea,
even if you thought of it,
and have spent years thinking about it.

If a potential investor is going to take the time, money, and bother to steal your idea,
then someone else is going to buy it from you
before they have a chance.

me, talking to Stephen Strudwick about startups, already in Beta, being too scared to pitch to investors!
Comments (View)

Rendering layouts that live in /public?

At work we have the following concept.

  1. a “site” has a subset of our content
  2. a “site” has a url - eg. “oursite.com/stickers” or “stickersNOTvicars.com”
  3. a “site” can have its own customised layout, or fall back to the default one

How does this work in code?

  1. site.articles (pretty simple)
  2. a whole load of “route filters” that match the incoming host
  3. the code I’m writing about

So, historically we did

class ApplicationController
  layout :determine_layout
  def determine_layout
    if File.exists?("#{Rails.root}/public/sites/#{@site.id}/application.rhtml")
      "../../public/sites/#{@site.id}/application"
    else
      "site_default"
    end
  end
end

This was a hack, and it breaks with Rails 2.1.1, so after a day or so playing with the internals of ActionView I discovered this;

append_view_path("#{Rails.root}/public/sites")

And it works!

We just need to set;

"#{@site.id}/application"

as our layout, and we’re away.

Site-specific layouts that live in /public!

Comments (View)