InquiryLabs

Politics, Programming and Possibilities

Archive for the ‘Uncategorized’ Category

Ruby Hashes of Arbitrary Depth

UPDATE: In the comments, Kent has provided a complete solution to this problem:

hash = Hash.new(&(p=lambda{|h,k| h[k] = Hash.new(&p)}))


I would love to see this integrated in to the Hash class at some point, but if not, we can (with Ruby’s kind acceptance) do it ourselves:

class Hash
  def self.arbitrary_depth
    Hash.new(&(p=lambda{|h,k| h[k] = Hash.new(&p)}))
  end
end


Thus,

hash = Hash.arbitrary_depth


While working on FamilyLearn.com today, I ran in to an interesting Ruby puzzle–how do you create a PHP-like Hash object that accepts keys to an arbitrary depth?For example, the following will not work in Ruby:
h = Hash.new
h[:one][:two] = "uh-oh!"
# NoMethodError: undefined method `[]=' for nil:NilClass

The solution? Pass in a proc that will tell Hash to create a second hash by default for each key that is not found:

h = Hash.new { |h,v| h[v]= Hash.new }
h[:one][:two] = "uh-oh!"
# => "uh-oh!"
h
# => {:one=>{:two=>"uh-oh!"}}

Much better. But that’s only two-deep. What about n-deep? The solution I found isn’t fully “arbitrary” on demand, but it should work for most cases:

class ArbitraryDepthHash
  def self.arbitrary_depth_proc(depth = 1)
    proc { |h,v| h[v] = Hash.new(&arbitrary_depth_proc(depth-1)) }
  end

  def self.[](depth)
    Hash.new(&arbitrary_depth_proc(depth))
  end
end

h = ArbitraryDepthHash[5]
h[:one][:two][:three][:four][:five] = "wow!"
# => "wow!"
h
# => {:one=>{:two=>{:three=>{:four=>{:five=>"wow!"}}}}}

Updated ColumnComments Plugin (v.1.2)

Gerardo Lisboa recently enquired about the ColumnComments plugin, noting that comments can not be added to columns during the creating of a table (usually the most useful time to add comments!) He is, of course, absolutely right–the comments option did not work in version 1.1. In response, I wrapped up a zip file of my current implementation and sent him the update.

For anyone else who is using ColumnComments, I recommend using this upgrade (MySQL only).

Download the zip file here, and then unzip it in to your Rails app’s vendor/plugins directory.

How to Use cURL to Test RESTful Rails

I’ve begun experimenting with the new Edge Rails code that includes built-in support for REST. (The code that was once in the simply_restful plugin is now a part of Edge Rails.) With the capability to generate multiple types of output per action, it has become more and more useful to test actions on the command-line using cURL. Here are some useful cURL parameters I’ve used:

  • -X [action]: Allows you to specify an HTTP action such as GET, POST, PUT or DELETE.
    Example:

    curl -X DELETE http://localhost:3000/books/1
  • -d [parameter]: Lets you set variables as if they were POSTed in a form to the URL. Note that this automatically makes the request a POST HTTP action type (no -X necessary).
    Example:

    curl -d "book[title]=Test" -d "book[copyright]=1998"
    http://localhost:3000/books
  • -H [header]: Gives you the option of setting an HTTP header such as Content-Type or Accept. This is particularly useful for requesting text/xml as the Accept type.
    Example:

    curl -H "Accept: text/xml"
    http://localhost:3000/books/sections/1

Putting it all together, here’s a cURL command that updates the title of a Book object using the PUT action and expects an xml response:

curl -H "Accept: text/xml" -X PUT -d "book[title]=Testing Again"
http://localhost:3000/books/1

Rails Plugins Directory at AgileWebDevelopment

Benjamin Curtis has been seeding his Rails Plugins Directory project by taking announcements on the Rails list and documenting them on his website. He added tags a while back, and the list of plugins is now very impressive!

Take a look yourself and see if you like it.

I had a doozy of a bug today: an “Album” model has_many “Track” objects, but calling album.tracks.clear was not deleting or destroying the associated tracks in spite of my having explicitly set :dependent => :destroy on the has_many association.

As it turns out, my object (the album) was being stored in the session, and therefore the associated tracks were also in the session. When I called album.tracks.clear, the foreign keys were nullified instead of the rows destroyed.

The solution: store album ids in the session instead of the whole object, and do an Album.find(session[:album_id]).

ActiveRecord::Errors#to_xml

Here’s a method that will allow you to call to_xml on an ActiveRecord::Errors object. We’re using this to pass errors between web apps via a web service api.

class ActiveRecord::Errors
  def to_xml(options = {})
    options[:indent] ||= 2
    options.reverse_merge!({ :builder =>
      Builder::XmlMarkup.new(:indent =>
        options[:indent]), :root => "errors" })
    options[:builder].instruct! unless options.delete(:skip_instruct)

    options[:builder].__send__(options[:root].to_s.dasherize) do |xml|
      @errors.each do |key, value|
        xml.__send__(key.to_s.dasherize) do |xm|
          for message in value
            xm.message(message)
          end
        end
      end
    end

  end
end

Textmate Snippets Like

So here’s an idea I’ve been tossing around on the Textmate IRC channel and mailing list: What if Textmate supported multiple arbitrary simultaneous carets (MASC)? Allan Odgaard didn’t like the idea on first inspection, because it involves using the mouse–something that he is philosophically opposed to (for obvious reasons–it’s a text editor, after all). But I think there’d be many people who would receive this feature with eager arms and an appropriate amount of salivation.

So what is the idea? Here’s my original mailing list post:

What if you could add multiple carets to the current document by command-clicking? I imagine this to work in a way almost identical to that of the current snippet mechanism. For example: choose three caret locations, start typing, and in each location your text will show up. Press tab and the caret will focus in on the second of the two locations, highlighting the newly typed text (if any). Tab again and it moves to the third.

It would also be ideal to be able to highlight multiple selections in the same way–kind of like a powerful replace mechanism. Command-click and select three words in the document, then type one new word, and incrementally, all three words change to the new one.

Here is a screencast of MASC in action (Quicktime, 27 MB):

Textmate - multiple arbitrary simultaneous carets


Download

Update: The bundle is available as a disk image here. Key bindings and the “ß” marker character are subject to change. Use alt-s to mark and alt-f to convert markers to a snippet.

Update #2: No longer uses the beta marker. Uses special angle brackets instead.

Update #3: There is now a that has updated information and a new (shorter) screencast.

Rails Bundle for TextMate 1.0 RC3

New Way of Accessing Ruby

My friends on IRC have helped me track down and understand better the way TextMate helps its bundles by setting up the environment for Ruby code. The Rails bundle now uses the TM_RUBY environment variable to determine which ruby on your system to use (i.e. if you have multiple ruby shell commands installed).

One of the biggest problems with this environment stuff has been trying to figure out the best way to support all of the many ways you can get Ruby on your system: the built-in version patched with fixrbconfig, DarwinPorts, your own version, or perhaps even Locomotive’s ruby-in-a-box. For those of you who’ve been experiencing problems with past versions of the Rails bundle, I think this one may fix it for you. If you’re still having problems, try adding a TM_RUBY environment variable to your TextMate shell variables (in Preferences, go to Advanced, then Shell Variables). Point TM_RUBY to the location you installed ruby at.

As usual, please feel free to contact me and we can try to work out a solution if you’re still having trouble. Comments showing your problems or solutions are also welcome.

Download


Download the Disk Image
TextMate Rails Bundle 1.0 RC3

"syncPeople on Rails" 0.6

Due to some great comments already, I decided to fix up what I can for the night and wrap this up. Version 0.6 will ask you before overwriting an already-existing partial, and the Intelligent Go To File command is a little bit more robust.

There’s also a subversion repository of this TextMate bundle at:

svn://syncid.textdriven.com/svn/opensource/syncpeople_on_rails/trunk

You can download version 0.6 here.

The original announcement of version 0.5 can be found here.

qforms á=á=á=á=á= dynarch_calendar á=á=á=jstree

á= á=á=lightbox jsá=á=á= stateful_formá=á=á= á=textarea tools

Bundles that include javascripts, stylesheets and images are getting easier and easier. It’s a wonderful time to be a Rails developer :)

For those who would like to know what bundled_resource is, check out my earlier post that introduces the problem and solution offered by this package.

This release marks a much improved and nearly completely rewritten dynarch calendar bundle. Here’s what’s new:

  • It is no longer necessary to call convert_date_to_multi_params! in your controller
  • Backwards compatibility for non-javascript browsers. Calling dynarch_date_select now calls the built-in rails date_select method so that users who have browsers without javascript can still select a date in a reasonable way.
  • There is no longer an obnoxious “:date” field in the returned multiparameter values.
  • Bundles now accept optional parameters. For the dynarch_calendar bundle, you can specify the color, language and icon for your dynarch calendar.
  • 12-hour time is handled in a novel way, so that the user enters a 12-hour time (e.g. 3 PM) and Rails can read it as if it’s a 24-hour time
  • Better documentation.

Version 0.9 of bundled_resource now also includes a “stateful_form” bundle that makes it easier to store the open/closed states of form sections. This is particularly useful for AJAX forms that have hidden sections that the user can open up. When the form is submitted to the server and returned with an error, the form will retain its open/closed states so that it’s just as the user expects it.

You can download bundled_resource 0.9 here (345 KB) or use the subversion repository directly:

svn://syncid.textdriven.com/svn/opensource/bundled_resource/trunk

Compliments of syncPEOPLE social conference software development