The Dev Blog

Putting Family Management on Rails!

Hash for views

Posted by Guy Naor Wed, 24 May 2006 21:40:00 GMT

One of my team members asked for a way to use non ActiveRecord objects in views. We settled on a modified hash that will have accessors for all the keys. Pretty simple with method_missing()

class ObjectiveHash < Hash

  def method_missing(method_id, *args, &block)
    begin
      super
    rescue NoMethodError => e
      is_assign = method_id.to_s[-1,1] == '='
      the_key = (method_id.to_s[0..(is_assign ? -2 : -1)]).to_sym
      self[the_key] = args if args && is_assign
      raise e if !self[the_key]  
      return self[the_key]
    end
  end

  private 
  def initialize other_hash = {}
    super
    update(other_hash)
  end

end

Now we can pass it to the view, and retireve into it on submit:

    
# Setting values
@settings = ObjectiveHash.new
@settings.name = "John"
@settings.family = "Doe"

# Getting values on submit
@settings = ObjectiveHash.new params[:settings].symbolize_keys

# Accessing the values
@settings.name # => John
@settings.family # => Doe

Please note that it'll be slower than regular hash access (which still works), and that all keys are symbols.

Posted in ,  | 5 comments | no trackbacks

del.icio.us:Hash for views digg:Hash for views spurl:Hash for views wists:Hash for views simpy:Hash for views newsvine:Hash for views blinklist:Hash for views furl:Hash for views reddit:Hash for views fark:Hash for views blogmarks:Hash for views Y!:Hash for views smarking:Hash for views magnolia:Hash for views segnalo:Hash for views

Comments

  1. trans said about 6 hours later:

    You might run into some name clashes. Try @settings.class = "foo" for instance.

    Why not just use the built-in OpenStruct? Or for an even more robust solution have a look at Facet's OpenObject.

  2. Guy Naor said about 6 hours later:

    The problem with using OpenStruct is that it's not enumerable and doesn't interchange with hash, so it's a bit less convenient. The problem with assigning to the class element is the same with OpenStruct as well, and probably with OpenObject (haven't seen it yet), as it's a method of every class in ruby.

  3. trans said about 16 hours later:

    Right, it wouldn't be Enumerable b/c that adds yet another set of methods that could name clash.

    OpenObject doesn't suffer from the "class" problem since it subclasses BasicObject (ie. BlankSlate) clearing out most methods. As for Enumerable, you have the same problem of course. It does have a #to_h method though and it can also be used with Enumerator (becuase #each works).

  4. Guy Naor said about 17 hours later:

    Thanks for pointing me to OpenObject. I'll have to look at it.

    BTW, each does work on this modified hash as it's just a hash. But indeed you have to be careful with name clashes. We had this problem with a field named zip we needed for address, as zip is also an Enumerable method. We just changed it to zipcode.

  5. Rick Hull said 1 day later:

    I can confirm that OpenStruct works perfectly for this purpose:

    e.g.

    require 'ostruct' @example = OpenStruct.new params[:example] render :partial => 'example_form', :object => @example

    For me anyways. I had a clunky hand-rolled class for each form partial, and this was a drop-in replacement.

Trackbacks

Use the following link to trackback from your own site:
http://devblog.famundo.com/articles/trackback/15

Comments are disabled

Subscribe to The Dev Blog