Smokes your problems, coughs fresh air.

Tag: Rails

Silent change in URLs of Ruby on Rails svn repository

I don’t know why, but everything associated with Ruby on Rails seems to change all the time, without notice, or (in the case of URLs) without redirect.

We used http://svn.rubyonrails.org/rails for our svn:external deployment of rails 1.2.6. But that suddenly stopped working. The Ruby on Rails weblog doesn’t contain any information on it (that I can find), going to svn.rubyonrails.org with my web browser yielded just the front page of the weblog and Googling didn’t help much. That is, until I accidentally found http://dev.rubyonrails.org/svn/rails.

So, I changed the svn:externals from “rails http://svn.rubyonrails.org/rails/tags/rel_1-2-6/” to “rails http://dev.rubyonrails.org/svn/rails/tags/rel_1-2-6/” and now it works again.

Native PostgreSQL authentication in Rails with rails-psql-auth

A while ago, I wrote a PostgreSQL auth plugin for Rails. The plugin basically defers all authentication and authorization worries to the database layer where they are supposed to be taken care of anyway.

Using this plugin, the user is asked for his or her credentials using a HTTP Basic authentication challenge. (The code for this is adapted from Coda Hale‘s Basic HTTP authentication plugin.) It’s possible to specify a guest_username in the database.yml which will be used as a fall-back if no credentials are supplied. After successful login or if a guest user is found, the plugin will make sure that all database operations run as that user. If any operation fails due to insufficient user rights, the user will be prompted for a username/password pair again.

Detailed and up-to-date documentation for the plugin can always be found at the plugin’s homepage. Go to the plugin’s project page for getting help or for reporting issues with the plugin.

Nested hashes derail Rails’ url_for helpers

While working on the Sicirec PostgreSQL database front-end today, I had to pass a lot of nested parameters to a link_to helper in Rails. Software being what it is, this didn’t work.

There are a few patches awaiting acceptance. The most promising of these patches was part of an open Trac ticket. Because we use Rails as an svn external, applying the patch myself wouldn’t work when deploying unless I’d create a vendor branch for Rails in our own repository. Hoping that someone had forgotten to close the ticket, I first tried to upgrade to Rails 1.2.2, which was about time anyway because we were still in the 1.1 branch. The upgrade went fine but didn’t fix the problem.

Next, I tried to integrate the patch by redefining the methods changed by the patch in our lib/ directory. When this didn’t work, I decided to simply do some flattening of the hash myself for this one particular case.

A bit of googling around gave me many clues that the problem has cost a lot of people lots of time already.

Eventually, I settled with a derivate of some code by Peter Marklund to flatten my hashes:

class Hash
  # Flatten a hash into a flat form suitable for an URL.
  # Accepts as an optional parameter an array of names that pretend to be the ancestor key names.
  #
  # Example 1:
  #
  #   { 'animals' => {
  #       'fish' => { 'legs' => 0, 'sound' => 'Blub' }
  #       'cat' => { 'legs' => 4, 'sound' => 'Miaow' }
  #   }.flatten_for_url
  #
  #   # => { 'animals[fish][legs]'  => 0,
  #          'animals[fish][sound]' => 'Blub',
  #          'animals[cat][legs]'   => 4,
  #          'animals[cat][sound]'  => 'Miaow'
  #        }
  #
  # Example 2:
  #
  #   {'color' => 'blue'}.flatten_for_url( %w(world things) )  # => {'world[things][color]' => 'blue'}
  #
  def flatten_for_url(ancestor_names = [])
    flat_hash = Hash.new
 
    each do |key, value|
      names = Array.new(ancestor_names)
      names << key
 
      if value.is_a?(Hash)
        flat_hash.merge!(value.flatten_for_url(names))
      else
        flat_key = names.shift.to_s.dup
        names.each do |name|
          flat_key << "[#{name}]"
        end
        flat_key << "[]" if value.is_a?(Array)
        flat_hash[flat_key] = value
      end
    end
 
    flat_hash
  end
end

As you can see, I turned my code into a single method of the Hash class. It can be used simply in any url_for (based) call as in the following example:

url_for {
    :controller => 'post',
    :action => 'new',
    'author' => {'name' => 'Rowan', 'gender' => 'm'}
  }.flatten_for_url
  # => /post/new?author[name]=Rowan&author[gender]=m 

Now if only some Rails developer would commit the patch already.

© 2024 BigSmoke

Theme by Anders NorenUp ↑