Tag Archives: ruby

Saving Omniauth Provider Data in the Database

I spent some time searching for a way to not need the App ID and Secret Key for OmniAuth in an initializer. Luckily I ran across a post mentioning this link:

https://github.com/intridea/omniauth/wiki/Setup-Phase

By following these instructions, you can wait and set the App ID and Secret key at request time. In my case, I’m going to pull it out of a database table which stores config items.

My Current Code looks like this:

unless Rails.env.nil?
  CONFIG = YAML.load_file(Rails.root.join("config/secrets.yml"))[Rails.env]

  Rails.application.config.middleware.use OmniAuth::Builder do
    provider :facebook, CONFIG['fb_app_id'], CONFIG['fb_secret_key'], :scope => 'email,user_about_me,user_activities,user_birthday,user_groups', :display => 'popup'
  end
end

And the future code will look like this:

SETUP_PROC = lambda do |env| 
  config = Config.find(:first)
  env['omniauth.strategy'].options[:consumer_key] = config.facebook_key
  env['omniauth.strategy'].options[:consumer_secret] = config.facebook_secret
end
   
use OmniAuth::Builder.new do
  provider :facebook, :setup => SETUP_PROC
end

Tagged , , ,

HOW TO GET DOMAIN OBJECTS IN JAVASCRIPT WITH RAILS (PART 2)

The next step in the sequence for loading Rails objects in javascript is to dynamically get them from the script. To do this, I’m going to use the JQuery “Get” method. I’ll be hitting the same URL that I set up in the last post.

Once I get the object, I’ll just add a simple alert method to the script, so I can be sure that I loaded the data correctly (or you could use a javascript debugger…).

    $.get("/restaurants/recommendations", function(restaurant) {
      alert("successfully loaded: " + JSON.stringify(restaurant));
    });

Once I’ve confirmed that I have the correct object, I want to get the latitude and longitude values from the object and create a marker on the map that I have already set up.

  $.get("/restaurants/recommendations", function(restaurant) {  
    
    var myMarkerLatLng = new CM.LatLng(restaurant.lattitude, restaurant.longitude);
    var myMarker = new CM.Marker(myMarkerLatLng, {
      title: restaurant.name
    });
    map.addOverlay(myMarker);
    
  });

When I put it all together the entire javascript function looks like this:

$(document).ready(function(){ 
  
  var cloudmade = new CM.Tiles.CloudMade.Web({key: 'my_key'});
  var map = new CM.Map('map_canvas', cloudmade);

  map.setCenter(new CM.LatLng(35.998743, -78.90723), 13);
  map.addControl(new CM.LargeMapControl());

  $.get("/restaurants/recommendations", function(restaurant) {  
    
    var myMarkerLatLng = new CM.LatLng(restaurant.lattitude, restaurant.longitude);
    var myMarker = new CM.Marker(myMarkerLatLng, {
      title: restaurant.name
    });
    map.addOverlay(myMarker);
    
  });
    
    
});

And I get to see my “Watts Grocery” marker on the map.

Tagged , , , , ,

How to Parse XML with Ruby

With one of my side projects, I’ve been investigating how to integrate maps with a Rails application. One of the tasks for a proof of concept was to mock up some reviews for restaurants, and I came across the Overpass API, which exposes a nice interface for getting lists of map items.

To get an XML document with the list of restaurants in your area, you simply submit a http get request to the properly formed URL… like so:

http://www.overpass-api.de/api/xapi?node[bbox=7.1,51.2,7.2,51.3][amenity=restaurant]

The bbox attribute specifies the “bounding box” of the area you want to search as latitude and longitude coordinates.
The output from the query will give you xml that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="Overpass API">
<meta osm_base="2012-03-11T22:12:02Z"/>
  <node id="266302295" lat="36.0164193" lon="-78.9189592">
    <tag k="amenity" v="restaurant"/>
    <tag k="created_by" v="Potlatch 0.9a"/>
    <tag k="name" v="Watts Grocery"/>
  </node>
  <node id="266814066" lat="36.0139023" lon="-78.9215805">
    <tag k="amenity" v="restaurant"/>
    <tag k="created_by" v="Potlatch 0.9a"/>
    <tag k="name" v="Magnolia Grill"/>
  </node>
  <node id="266814217" lat="36.0106114" lon="-78.9222843">
    <tag k="amenity" v="restaurant"/>
    <tag k="created_by" v="Potlatch 0.9a"/>
    <tag k="name" v="Vin Rouge"/>
  </node>
...
</osm>

I took this XML and saved it to a file named restaurants.xml

After you have the XML, you sill need to parse it. To do that, I used REXML which is built into the ruby library. For this example, I create a “Restaurant” object for each of the XML nodes, and parsed it using XPath expressions to get the values I cared about. Then I saved off the values and made sure each object was saved to my DB.

xml = File.read('./lib/restaurants.xml')

require 'rexml/document'
doc = REXML::Document.new(xml)

doc.elements.each('osm/node') {|x|
   r = Restaurant.new
   r.name = x.elements["tag[@k='name']"].attributes["v"]
   r.openmap_id = x.attributes["id"].to_i
   r.latitude = x.attributes["lat"]
   r.longitude = x.attributes["lon"]
   r.save
}

Tagged , , ,

Playing with OpenStreetMap and Cloudmade

I’ve been doing some research into using maps in a web application, and I wanted to check out the different providers that are available.  Since hearing that Apple was moving away from the Google Maps API in iPhoto, I was curious to give it a try myself.

Since OpenStreetMap is a “free” alternative for mapping data, I looked around and CloudMade.com was the first provider with an API that I was able see an easy way to use.  It works very similar to Google Maps, and has a similar javascript API.

Here’s how I added it to a simple Rails 3 app…

First, I created a new controller “app/controllers/maps_controller.rb” and put an index function in:

class MapsController < ApplicationController
  def index
  end
end

Next, I created a separate javascript doc “app/assets/javascript/maps.js”:

$(document).ready(function(){ /*code here*/ 
    var cloudmade = new CM.Tiles.CloudMade.Web({key: 'my_key'});
    var map = new CM.Map('map_canvas', cloudmade);

    
     var geocoder = new CM.Geocoder('my_key');
  
    geocoder.getLocations('Durham, NC', function(response) {
      var southWest = new CM.LatLng(response.bounds[0][0], response.bounds[0][1]),
	      northEast = new CM.LatLng(response.bounds[1][0], response.bounds[1][1]);
      map.zoomToBounds(new CM.LatLngBounds(southWest, northEast));
      
    });
   
    map.addControl(new CM.LargeMapControl());
});

Next, I created the maps index view “app/views/maps/index.html.rb” with a link to the open maps javascript library and the maps javascript doc:

<% content_for(:head) do %>
<%= javascript_include_tag "http://tile.cloudmade.com/wml/latest/web-maps-lite.js", :maps %>
<% end %>

<script>
  user = <%= current_user %>
</script>

<br />
<br />
<div id="map_sidebar">Top Restaurants </div>
<div id="map_canvas"></div>

Finally, modify the routes.rb file to allow localhost:8080/maps to be directed to my new controller and view:

  match "/maps" => "maps#index"

Add this all up and we get a nice map showing on our page:

The only weird thing I noticed is that there are some issues when zooming in.  After a certain point, the tiles stop loading:

If you’re interested in learning more, the CloudMade tutorials show pretty much how to do everything in easy steps here.

Tagged , , , , , ,