Using TempObject with a search form

Here is how I use TempObject with a search form.

I’ll use an example of creating a form to return balls. In the controller I first create a TempObject with the attributes I want to offer in the search form:

@ball_search = TempObject.new(:colour, :size)

I can then use standard Rails form helpers to create the search form within a view:

<% form_tag do %>
  <p>Colour:  <%= text_field 'ball_search', 'colour' -%></p>
  <p>Size:  <%= text_field 'ball_search', 'size' -%></p>
  <p><%= submit_tag("Search for balls") -%></p>
<% end %>

It is then easy to gather the data passed from the form and load the @ball_search object with it by adding this line into the controller (below the statement creating the object):

@ball_search.load_data(params[:ball_search]) if params[:ball_search]

The data can then be used to find the balls with these attributes:

Ball.find(:all, 
  :conditions => ["colour = ? AND size = ?",
          @ball_search.colour,
          @ball_search.size])

This is a simple example, where I’ve just used text_field form helpers, but it works just as well with the other standard Rails form helper elements.

You can also use @ball_search.attribute_names to create the find conditions:

search_query = Array.new
search_data = Array.new
for name in @ball_search.attribute_names
  search_query << "#{namd} = ?"
  search_data << @ball_search.send(name)
end
Ball.find(:all, 
  :conditions => [search_query.join(" AND "), 
          search_data].flatten)

With that solution, if another search criteria needs to be added, all that is needed is to add the extra criteria to the original object creation statement and then add the extra form field.

controller:

@ball_search = TempObject.new(:colour, :size, :sport)

view:

<% form_tag do %>
  <p>Colour:  <%= text_field 'ball_search', 'colour' -%></p>
  <p>Size:  <%= text_field 'ball_search', 'size' -%></p>
  <p>Sport:  <%= text_field 'ball_search', 'sport' -%></p>
  <p><%= submit_tag("Search for balls") -%></p>
<% end %>

The code to gather all the data together and populate the find query remains the same.

Posted in Ruby | Comments Off on Using TempObject with a search form

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
Posted in Ruby | Comments Off on Temp Object

A tale of two vomits

When I was first training to become a Community First Responder (CFR), my main worry was that I would not be able to handle a patient being physically sick. The first time I had to deal with such a situation (a drunk with a head injury), it was a great relief when the vomit did not bother me.

I think the reason I am not greatly affected is three fold: there is already enough to deal with; I tend to go into “CFR mode” during a call and all I really think about it what needs to be done; and to be honest it is a lot easier to deal with when you are not the one who will have to clean it up.

In fact, when that first drunk was sick, all that went through my mind was to make sure my kit was well clear of it.

Since then dealing with vomit is just part of the job and almost the most notable part of it, is having the thought “I should be affected by that, but I’m not”.

So my last two call outs have been unusual. The first was to a lady who was sick every few minutes. It was difficult to workout what was going on as answers to questions such as “Have you any long term illness” solicited the replay “I’ve got everything”. Fortunately the crew were with me very quickly and I could pass her over to them.

However, the thing that sticks in my mind is she was being sick into a bowl, and we have exactly the same bowl at home. The peelings for our compost go in it. Now every time I go into the kitchen I see the bowl and an image of the woman vomiting into it comes into my head. It’s quite disconcerting.

The second call-out was more serious. A lady in her nineties had been sick. When I got there all she seemed to be concerned about was the vomit over her bed. She was confused and I was able to reassure her that we could deal with that.

However, when I felt her pulse, I knew the vomit wasn’t the main worry. 12 beats in 15 seconds with the last 3 very irregular.
Time to get the Oxygen out. As I was getting that ready the ambulance arrived outside.

The paramedics used an ECG to see what was going on and there seemed to be good indications that the lady was having an MI.

So I’d picked up the underlying issue that needed immediate treatment in spite of having to deal with an unpleasant scene on arrival. I’d got oxygen on early and successfully helped the paramedics. So a very satisfying call-out for me.

And fortunately – no familiar kitchen equipment in sight.

Posted in Community First Responder | Comments Off on A tale of two vomits

Using a shared location for common code

I am a book lover, and have built up a lot of my Ruby and Rails knowledge from an ever expanding collection of books. No matter how big or small, most give me some new information or way of dealing with a problem. One of my most recent books is a little gem : Rails Pocket Reference by Eric Berry.

One bit of information I got from that was how easy it is to enter an alternative code location into your Rails configuration. It is in fact very easy, and for me was definitely a “why haven’t I done this before” moment.

All you need to do is add a

config.load_paths

declaration to the Rails application’s config/environment.rb. It needs to go within the

Rails::Initializer.run

loop. For example:

Rails::Initializer.run do |config|
  config.load_paths += %W(#{RAILS_ROOT}/../useful_objects/lib)
end

Information about doing this is there and clear in the default environment.rb so more fool me for not sussing this before.

The path in the example allows me to create a Ruby application called “useful_objects” in the same folder as my Rails applications. Any class definitions I put in the lib folder there are then available to any application that has “useful_objects” in its load path. It also gives me a central location where I can put modules for including into other classes. It also gives me a location to put unit tests for these shared classes and modules (userful_objects/test)

The more common way to manage this is probably with plug-ins. What I like with the load_path method is that I only have one place to update. If I add a new method or refactor I only need to do it in one place. Of course that could add more complication, but with me running just 3 Rails applications sharing the code, it is manageable. If I had more applications, or they were not all in the same location, then the plug-in route would be better I think.

Using a single shared location has allowed me to strip out a lot of duplication between applications: especially for things like user handling and basic text modifications. It has allowed me to slim down my main applications and make them clearer, and for me it is easy to manage.

Posted in Ruby | Comments Off on Using a shared location for common code

A new blog!

I thought it about time I started my own blog, as the ramblings of another bearded buffoon, is just what the Internet needs.

Mainly I hope it will let me flesh out my Ruby and Rails notes that I’ve previously published here:

http://www.nicholshayes.co.uk/RailsWiki.html

However, it will probably include entries about my other interests which include general IT and network management, voluntary work, and script writing.

Posted in Blog | Comments Off on A new blog!