我在Ruby on rails网站上有一些脚本来查找位置并将记录保存到我的数据库中。
此时如果找不到位置,它将返回Nil并仍然保存到数据库。
我希望它出错并继续解析文件的其余部分,而不是将nil值保存到数据库中。
将数据库修改为该列上的NOT NIL,或者如果编码中的值为n,则有办法返回Error
如下所示
Begin
SQL Query
rescue
return error if Nil
end
模型
class Hotload < ActiveRecord::Base
attr_accessor :log
validates :user_id, :uniqueness => {:scope => [:comments, :origin, :dest]}
attr_accessible :comments, :covered, :delivery, :dest, :equipment_id, :length, :ltl, :origin, :pickup, :rate, :user_id, :weight, :source
belongs_to :user
has_one :equipment
set_rgeo_factory_for_column(:origin, RGeo::Geographic.spherical_factory(:srid => 4326))
set_rgeo_factory_for_column(:dest, RGeo::Geographic.spherical_factory(:srid => 4326))
before_save :add_city_and_state
has_one :company, through: :user
def self.post(post)
#convert the post to hash of strings
post = post.stringify_keys
begin
['origin','dest'].each do |loc|
state = post[loc][-2,2]
city = post[loc].gsub(%r(, [a-zA-Z]+), '').strip
post[loc] = LocationFinder.call(city, state, "true")
end
post.keys.each do |key|
if post[key] == ''
post.delete(key)
end
end
l = Hotload.where(:origin => post['origin'],:dest => post['dest'],:comments => post['comments']).first_or_create do |h|
h.origin = post['origin']
h.dest = post['dest']
h.comments = post['comments']
h.delivery = post['delivery']
h.pickup = post['pickup']
h.equipment_id = post['equipment_id']
h.source = post['source']
h.user_id = post['user_id']
h.length = post['length']
end
l.touch
l.save # called so that we update the 'updated_at' field if we find the record above
rescue Exception => e
puts e unless Rails.env.test?
end
end
辅助
#takes in a city and state
# then looks in the database for the locations
# if they are not found, it attempts to find the location using Bing/Google
#
# Is_hotload is a placeholder that is used to determine how we report on unknown locations
# if we get an unknown location, we try to add it immediately if it is a hotload
# otherwise we only try to add it if it has been reported 10 times
#
# Returns either NIL or a POINT string representing the Location in the format "POINT (#{origin.coords.x} #{origin.coords.y})"
class LocationFinder
def self.call(city, state, hotload)
raise Error if [city,state].include? nil
LocationFinder.new(city, state, hotload).find_location
end
attr_accessor :city, :state, :hotload, :lat, :lng
def initialize(city, state, hotload)
@city = city.to_s.try(:downcase)
@state = state.to_s.try(:downcase)
@hotload = hotload
end
# for testing purposes only
# @lat = "37.208969116210938"
# @lng = "-93.291557312011719"
def find_location
location = validate_location
location ||= search_database
location ||= search_levenshtein
location ||= search_unknown
unless location.nil? || location.empty?
location.try(:coords)
end
end
def validate_location
[city,state].each do |val|
return "ANYWHERE" if val.blank?
return "ANYWHERE" if val.upcase == "ANYWHERE"
end
# if city =~ /\d{5}/
# city =
# end
nil
end
def search_database
Location.first(:conditions => {:city => city, :state => state})
end
def search_levenshtein
Location.where("(levenshtein(city, '#{city}') <= 4) AND state = '#{state}'").order("levenshtein(city, '#{city}') ASC").first
end
# Tries to find the location using an external API if it
# have a value greater than 10 or is a hotload
def search_unknown
cs = "#{city}, #{state}"
Report.check_and_add('unknown_locations', cs) unless hotload == "true"
report = Report.first( :conditions => { :metric => "unknown_locations", :name => cs } )
if report.value > 10 || hotload == "true"
begin
parse_geo_data
l = location_insert
if Location.city_state_exists?("#{city}, #{state}")
Report.delete(report.id)
end
rescue => detail
Report.new( {:name => cs, :metric => "Could Not Add", :value => '1', :reason => detail.to_s} ).save
end
end
end
def parse_geo_data
cs = "#{city}, #{state}"
puts cs
google_api_results = HTTParty.get("http://dev.virtualearth.net/REST/v1/Locations/#{cs.gsub(/ /, "%20")}?o=xml&key=AvtYnvs3UjKaIPdG5v1YaVBL_5-Rhg_zgUwoQgvTiTS9dMxJSreIanWVLvTzQc86")
geo_data = google_api_results.parsed_response
lat = geo_data["Response"]["ResourceSets"]["ResourceSet"]["Resources"]["Location"]["Point"]["Latitude"]
lng = geo_data["Response"]["ResourceSets"]["ResourceSet"]["Resources"]["Location"]["Point"]["Longitude"]
name = geo_data["Response"]["ResourceSets"]["ResourceSet"]["Resources"]["Location"]["Name"]
city, state = name.downcase.split(",")
state = state.strip
self.lat = lat
self.lng = lng
self.city = city
self.state = state
end
def location_insert
Location.create({:city => city, :state => state, :coords => "POINT(#{lng.to_f} #{lat.to_f})", :cs => "#{city}, #{state}"})
end
end
答案 0 :(得分:0)
在您的模型中添加状态验证将保持&#34;不良&#34;保存的数据:
validates :origin, :dest, :presence => true
您的l.errors
方法中的post
可以提供错误消息。如果您返回l
,那么您的调用代码可以reference those errors进行显示或记录。