Rails: найти или создать по виртуальному атрибуту - PullRequest
1 голос
/ 06 марта 2012

У меня какая-то сложная проблема, над которой я работаю в своем текущем приложении rails.В моем приложении пользователи делятся фотографиями.Фотографии могут быть связаны с городом, поэтому City has_many :photos.Я хочу, чтобы пользователи могли связывать свои фотографии с городом с помощью автозаполнения и синтаксиса на естественном языке.То есть: Нью-Йорк, Нью-Йорк или Париж, Франция.

Я хотел бы сделать это с помощью текстового поля автозаполнения, чтобы, если пользователь введет «Афины», он увидел бы список с:

Athens, Greece
Athens, GA

... и если бы человек действительно хотел «Афины, Техас», он мог бы просто напечатать это, и это создаст новую запись города.

В моей модели города есть поля, name, state, country.Штат и Страна - это двухбуквенные почтовые индексы (я использую Carmen для их проверки).У меня есть виртуальный атрибут с именем full_name, который возвращает «Город, код штата» (например, Нью-Йорк, Нью-Йорк) для городов Северной Америки и «Город, название страны» (например, Париж, Франция) для всех остальных.

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

Мой вопрос заключается в том, чтобы заставить текстовое поле работать, как я могу создать метод find_or_create, который может принимать строку с названием города и либо кодом штата, либо названием страны, а также находить или создавать эту запись?


Обновление

Вдохновленный ответом Кандады, я придумал что-то немного другое:

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

Это качает мойспецификации сейчас, так что я думаю, что моя проблема решена.

1 Ответ

2 голосов
/ 06 марта 2012
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

Теперь вы можете 'find_or_create_by _ *'

Photo.find_or_create_by_name(
  Photo.location_hash(location).merge(:name => "foor bar")
)
...