Temp Object

I found creating search forms in Rails a little awkward because most of the built in Rails form elements expect to work with attributes of an object, whereas for a search form I just needed to pass a set of attributes. The solution was simple – create a temporary object to hold search attributes.

When I first create the class I now use to solve this issue, I just intended to use it for search forms, but I now find I’m using it for other things such as organising the data returned by custom SQL calls.

Here is the class definition. I’ll add a couple of other blog entries to describe how I use it.

# An object used to store data
# Attributes can be generated both on initiation and later

# Usage
# t = TempObject.new('one')
# t.one = "Hi!"
# puts t.one     ---> "Hi!"
# t.create_attribute('two')
# t.two = "Hello again"
# puts t.two     ---> "Hello again"
class TempObject
  
  def initialize(*attribute_names)
    @attribute_names = Array.new
    attribute_names.flatten.each do |a| 
      create_attribute(a)
    end
  end
  
  # Creates a new attribute with a name defined by name
  # The example below generates two methods: the setter 'two=' and the getter two
  #
  # t = TempObject.new
  # t.create_attribute('two')
  # t.two = "Hello"
  # puts t.two   ---> "Hello"
  def create_attribute(name)
    name = name.to_sym
    self.class.send(:attr_accessor, name)
    @attribute_names << name
  end
  
  # Returns a list of the attributes added to this object
  def attribute_names
    @attribute_names
  end
  
  # Allows data to be loaded into the attributes from a Hash.
  # t = TempObject.new(:one, :two)
  # t.load_data({:one => 1, 'two' => 2, :three => 3})
  # puts t.one     ---> 1
  # puts t.three   ---> error no method
  def load_data(data = nil)
    if data
      @attribute_names.each do |a|
        if value = data[a.to_sym] or value = data[a.to_s]
          instance_variable_set("@#{a}", value)
        end
      end
    end
  end
  
  # Allows a new object to be created from a hash in one step
  # All data in hash will be used to populate new object
  # t = TempObject.new_and_load_all({:one => 1, :two => 2})
  # puts t.one   ---> 1
  def self.new_and_load_all(data)
    if data.kind_of?(Hash) and data.length > 0
      object = self.new(data.keys)
      object.load_data(data)
    end
    return object
  end

  # Takes an array of hashes (for example from a connection.select_all
  # and returns an array of TempOjects created from the hashes
  def self.create_from_array_of_hashes(array)
    array.collect{|hash| TempObject.new_and_load_all(hash)}
  end
  
  def report
    report_data = Array.new
    for attribute in attribute_names
      value = send(attribute)
      value = value.strftime("%a %d-%b-%y %H:%M") if value.kind_of? Time
      report_data << "#{attribute.to_s.capitalize} : #{value}" if value
    end
    return report_data
  end

end
This entry was posted in Ruby. Bookmark the permalink.