For those of you that don’t know, geokit is a great little gem that allows you to geocode addresses. It adds in very easy to use options in the ActiveRecord find method. Ex:
# will return all venues within 10 miles of the 10018 zip code Venue.find(:all, :origin => "10018", :within => 10)
The problem is that you can’t use geokit options in a named scope. Since searchlogic is named scope driven this presented a problem. So I wrote a little module that transfers geokit options from named scopes to the actual arguments of the method:
module GeokitForNamedScopes
OPTIONS = [:origin, :within, :beyond, :range, :formula, :bounds]
def find(*args)
super(*transfer_from_scope_to_args(args))
end
def count(*args)
super(*transfer_from_scope_to_args(args))
end
private
def transfer_from_scope_to_args(args)
find_options = scope(:find)
if find_options.is_a?(Hash)
options = args.extract_options!
OPTIONS.each do |key|
options[key] = find_options.delete(key) if find_options.key?(key)
end
args << options
else
args
end
end
end
class ActiveRecord::Base
class << self
def acts_as_mappable(*args)
result = super(*args)
extend GeokitForNamedScopes
GeokitForNamedScopes::OPTIONS.each do |key|
named_scope key, lambda { |value| {key => value} }
end
result
end
VALID_FIND_OPTIONS += GeokitForNamedScopes::OPTIONS
end
end
It’s far from perfect. The glaring problem is obviously redefining the VALID_FIND_OPTIONS constant, which throws a warning. But it works and it’s good enough for now. If anyone has any suggestions on how to improve this I’d to hear them. But you should be able to use geokit options in a named_scope with the above code. Ex:
Venue.origin("10017").within(10).all # => will return all venues within 10 miles of 10017
Geokit doesn’t really support making these calls through associations. But if you read the documentation. You will notice they do support this:
acts_as_mappable :through => :whatever
You can use that feature to bridge the gap
Hopefully this helps some of you.
Hello Ben,
Great stuff. But can you please explain me where to insert this module. I tried inserting it in /lib directory, but it did not work for me. Thanks in advance!!!
One more thing, I forgot to mention is that we configured application in spree. So our application is located in vendor/extensions directory.
You should be able to put it in config/initializers too, I think.
[...] Using Geokit with Searchlogic – Binary Logic [...]