Main

Hey, want to sort your query by geographic distance?

Nov 14 by Andre
Sure you do. Here's a sample Rails action which finds the ten closest cities to the latitude/longitude you provide. Obviously, this presumes your City model has the fields latitude and longitude. These examples are for MySQL 5.
def nearby_cities
  lat,lng=params[:ll].split(',').collect{|e|e.to_f}
 
  #convert to radians
  lat_radians=(lat/180) * Math::PI
  lng_radians=(lng/180) * Math::PI

  # 3963 is the earth's radius, more or less, in miles.
  # Which means that the distances you get out of this are in miles.
  # Want a different measure? Kilometers=6378. Nautical miles=3444. Furlongs=29544
  earths_radius = 3963
  table_name=City.table_name
  distance_sql=<<-SQL_END  (acos(cos(#{lat_radians})*cos(#{lng_radians})*
cos(radians(#{table_name}.latitude))*cos(radians(#{table_name}.longitude)) +
cos(#{lat_radians})*sin(#{lng_radians})*cos(radians(#{table_name}.latitude))*
sin(radians(#{table_name}.longitude)) +
sin(#{lat_radians})*sin(radians(#{table_name}.latitude))) * #{earths_radius})
  SQL_END

  cities = City.find(:all,
        :select=>"*, #{distance_sql} as distance",
        :order => 'distance asc',
        :limit => 10)
       
  render :text=>cities.collect{|c|c.attributes}.to_json
end
The key thing is the distance_sql, which does all the heavy lifting. You can take this basic formula and use it verbatim for any model with latitude/longitude columns -- just make sure you change the table_name to match your model.

Find within Radius

So, what if you want to constrain the results to a given radius? No problem. This finds all cities within a 25 mile radius:
  cities = City.find(:all,
        :select=>"*, #{distance_sql} as distance",
:conditions=>"#{distance_sql} <= 25",
        :order => 'distance asc')
Note that when you use distance in :conditions, you have to repeat distance_sql, whereas if you use distance in your order clause, you can simply reference the alias ("distance") which you gave the computed column in the select clause.

Utilizing that "distance" column

In the :select clause, you tacked an extra column -- distance -- on there. You can access this field just as you would any other (say from your .rhtml template): <%=city.name%> is <%=city.distance%> miles away.. Note that any of these add-on columns are treated by default as strings. If you want to format it as an actual number, you'll need to do something like <%=city.distance.to_f.ceil%> miles

Continue reading "Hey, want to sort your query by geographic distance?

Transferring a MySQL database structure and data to another machine

May 13 by Andre
This tutorial shows how to transfer a MySQL database from one box to another. There are lots of reasons you might want to do this --my motivation is that I develop on both a desktop at home, and on a laptop which I sometimes want to work on in a disconnected state (i.e., a cafe somewhere). These steps transfer both table structure and data, including keeping all your primary keys intact.

Continue reading "Transferring a MySQL database structure and data to another machine

Client does not support authentication protocol requested by server

Mar 24 by Andre
So I upgraded my local MySql server installation from 4.1 to 5.0. When I tried to generate scaffolds with Rails, I got a Client does not support authentication protocol requested by server; consider upgrading MySQL client.

If you run into this the answer is http://dev.mysql.com/doc/refman/5.0/en/old-client.html

In a nutshell, you have to run SET PASSWORD FOR 'some_user'@'some_host' = OLD_PASSWORD('newpwd');

Happy upgrading, MySQL users.

Continue reading "Client does not support authentication protocol requested by server