1

I have kind of a tricky problem I'm working on in my current rails app. In my app users share photos. Photos can be associated with a city, so City has_many :photos. I want users to be able to associate their photos with a city using autocomplete and a natural language syntax. Ie: New York, NY or Paris, France.

I'd like to do this with an autocomplete text box so that if the user types "Athens" they would see a list with:

Athens, Greece
Athens, GA

... and if the person actually wanted "Athens, TX" they could simply type that in and it would create a new city record.

My city model has the fields, name, state, country. State and Country are 2-letter postal codes (I use Carmen to validate them). I have a virtual attribute called full_name which returns "City, State Code" (like New York, NY) for North American cities, and "City, Country Name" (like Paris, France) for all others.

def full_name
    if north_american?
        [name, state].join(', ')
    else
        [name, Carmen.country_name( country )].join(', ')
    end
end

def north_american?
    ['US','CA'].include? country
end

My question is, to get the text field working, how can I create a find_or_create method that can accept a string with the city name and either state code or country name and find or create that record?


Update

Inspired by Kandada's answer I came up with something a little different:

def self.find_or_create_by_location_string( string )
  city,second = string.split(',').map(&:strip)
  if second.length == 2
    country = self.country_for_state( second )
    self.find_or_create_by_name_and_state( city, second.upcase, :country => country )
  else
    country = Carmen.country_code(second)
    self.find_or_create_by_name_and_country( city, country )
  end
end

def self.country_for_state( state )
  if Carmen.state_codes('US').include? state
    'US'
  elsif Carmen.state_codes('CA').include? state
    'CA'
  else
    nil
  end
end

This is rocking my specs right now, so I think my issue is solved.

Andrew
  • 42,517
  • 51
  • 181
  • 281

1 Answers1

2
class Photo < ActiveRecord::Base

  attr_accessor :location

  def self.location_hash location
    city,state,country = location.split(",")
    country = "US" if country.blank?
    {:city => city, :state => state,  :country => :country}
  end

end

Now you can 'find_or_create_by_*'

Photo.find_or_create_by_name(
  Photo.location_hash(location).merge(:name => "foor bar")
)
Harish Shetty
  • 64,083
  • 21
  • 152
  • 198
  • This wasn't *exactly* what I was looking for, but you inspired me and I think I found a workable solution. I'll append it to the question for reference. – Andrew Mar 06 '12 at 01:27