<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Elevated Code RSS Feed</title>
    <link>http://www.elevatedrails.com/rss/</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Elevated Code, providing custom software development.</description>
    
    
        <item>
          <title>Facebook IFrame applications and the new Open Graph API</title>
          <description>&lt;p&gt;
Facebook has long recommended that platform applications are developed using IFrames instead of FBML. Unfortunately, that has typically been a painful endeavor. Facebook typically has passed session information to the user as parameters on the first request to the iframe. The developer was required to store that information in a cookie if they wanted to persist it. Unfortunately, webkit based browsers (notably Safari and Chrome) don't allow cross domain cookies by default. This has caused some painful workarounds. Inside, I'll show you a painless one.
&lt;/p&gt; &lt;p&gt;
  To workaround the cross domain cookie problem, we'll need to get our application out of the iframe. A typical Facebook connect login button looks like:
&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
  &amp;lt;&lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;%=&lt;/span&gt;&lt;span style=&quot;&quot;&gt; fb_login_and_redirect root_url %&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
 In an IFrame application, this will redirect the IFrame to our site. When this happens, Safari and Chrome will block cookies. Instead, we want to redirect not just the IFrame, but the whole page. We'll use a new helper for that (Facbooker2 only right now)
&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
&amp;lt;&lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;% &lt;/span&gt;&lt;span style=&quot;&quot;&gt;fb_login&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt; &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;
  window.top.location = 'http://localhost:3000/'
&amp;lt;% end %&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;This gets us to our site without being in an IFrame. As the facebook connect process loads, we'll get the cookies set. If we were to then redirect back to the IFrame version of our page, we would have session information.
&lt;/p&gt;
&lt;p&gt;While this is functional, it's an odd user experience to have a page outside of facebook. Let's clean that up a little. I'm going to create an action to handle getting the session information. We don't need to do anything in the controller. When a webkit user visits this page, Facebook will be able to set the login cookie. This will call the &lt;code&gt;auth.login&lt;/code&gt; event to be fired. We can hook into that to send the user back to the IFrame page.
&lt;/p&gt;
&lt;p&gt; Our view looks like:
&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
&amp;lt;&lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;% &lt;/span&gt;&lt;span style=&quot;&quot;&gt;fb_connect_async_js2&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt; &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;
FB.Event.subscribe('auth.login', function(response) {
        window.location.href = &amp;quot;http://apps.facebook.com/canvas_url/&amp;quot;;
      });
&amp;lt;% end %&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;We could add a spinner or some other message to make it look a little nicer, but that's functional. Now, when a webkit user logs in they will be sent to our login specific page where the cookie will be set. Afterwards, they will be redirected back to the canvas url.
&lt;/p&gt;
&lt;p&gt;There's still one problem. If a user somehow makes it to our login page while already logged in, they will be stuck there forever. We can add just a little bit of our logic to our controller to handle that. 
&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;create&lt;/span&gt;
    redirect_to &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;http://apps.facebook.com/canvas_url/&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; current_facebook_user
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
Now, if the user is already logged in, we'll just redirect them back immediately. If they aren't, we'll wait for the login callback and will redirect them in the view.
&lt;/p&gt;
&lt;p&gt;
That eliminates one of the major problems plaguing Facebook IFrame applications. Shortly, I'll talk about how to make session handling work for logged in users so that you can use the built in Rails flash and session objects.
&lt;/p&gt;</description>
          <pubDate>Wed, 12 May 2010 06:36:44 GMT</pubDate>
          <guid>http://www.elevatedrails.com/articles/2010/05/12/facebook-iframe-applications-and-the-new-open-graph-api/</guid>
          <link>http://www.elevatedrails.com/articles/2010/05/12/facebook-iframe-applications-and-the-new-open-graph-api/</link>
        </item>
    
        <item>
          <title>Adding a UIActivityIndicator to a UIToolbar</title>
          <description>&lt;p&gt;
When building apps that fetch data from the network you may want to add an activity indicator to your application's toolbar. Unfortunately, there is no built in activity indicator bar item. Luckily, it's easy to create one in code.
&lt;/p&gt; &lt;p&gt;
 The key is to set the activity indicator as the custom view in a UIBarButtonItem:
&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
    &lt;span style=&quot;color:#038;font-weight:bold&quot;&gt;self&lt;/span&gt;.loadingIndicator = [[&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;UIActivityIndicatorView&lt;/span&gt; alloc] initWithActivityIndicatorStyle&lt;span style=&quot;color:#A60&quot;&gt;:UIActivityIndicatorViewStyleWhite&lt;/span&gt;];
    &lt;span style=&quot;color:#038;font-weight:bold&quot;&gt;self&lt;/span&gt;.activityBarItem.customView = &lt;span style=&quot;color:#038;font-weight:bold&quot;&gt;self&lt;/span&gt;.loadingIndicator;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
  That's all there is to it. You can create the bar item in IB and then create the indicator in the controller. Once you've created the indicator, just assign it to the customView property of the UIBarButtonItem. You'll want to set the width of the UIBarButtonItem to 20px in IB. I love simple solutions!
&lt;/p&gt;
</description>
          <pubDate>Thu, 29 Apr 2010 07:18:04 GMT</pubDate>
          <guid>http://www.elevatedrails.com/articles/2010/04/29/adding-a-uiactivityindicator-to-a-uitoolbar/</guid>
          <link>http://www.elevatedrails.com/articles/2010/04/29/adding-a-uiactivityindicator-to-a-uitoolbar/</link>
        </item>
    
        <item>
          <title>Speeding up delayed job</title>
          <description>&lt;p&gt;&lt;a href=&quot;http://github.com/tobi/delayed_job&quot;&gt;Delayed Job&lt;/a&gt; is a fantastic plugin for moving work out of the request flow. Unfortunately, it has a few performance problems when running with large numbers of jobs on MySQL. With minor changes, we can remove a large amount of the overhead.&lt;/p&gt; &lt;p&gt;
I noticed the performance problem on one of our applications when MySQL was taking large amounts of CPU. The application had been in production for about a year and had been performing well. I had just recently moved image resizing out of the main workflow and into delayed job. When I went to look at the &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.0/en/slow-query-log.html&quot;&gt;slow query log&lt;/a&gt;, I saw this being run frequently:
&lt;/p&gt;
&lt;code class=&quot;code&quot;&gt;
&lt;pre class=&quot;code&quot;&gt;
# Query_time: 0  Lock_time: 0  Rows_sent: 5  Rows_examined: 67604
SELECT * FROM `delayed_jobs` WHERE ((run_at &lt;= '2009-11-04 06:58:49' AND (locked_at IS NULL OR locked_at &lt; '2009-11-04 02:58:49') OR (locked_by = 'host:example.com pid:17731')) AND failed_at IS NULL)  ORDER BY priority DESC, run_at ASC LIMIT 5;
&lt;/pre&gt;
&lt;/code&gt;
&lt;p&gt;
When reading the output of the slow query log, I look mainly at two things. The first is the query time. In this case, the query was being run in less than a second. The second thing I look at is the ratio of the number of rows examined to the number of rows sent back to the app. In this case, the database had to look at 67,604 rows just to give the app 5 rows back. When you see full table scans like this, it is usually a sign of a missing index. I looked at the delayed jobs table and saw that there was only an index on ID. That means the DB was reading every row in the table for each query.
&lt;/p&gt;
&lt;p&gt;Once I realized that I was seeing a full table scan, I knew I needed to add an index. Normally, when you add indexes to a table, you're doing it to speed up the row selection performed by the where clause. That isn't a good idea here. Delayed job removes successfully completed records by default, and we have very few updates that fail. This means that the vast majority of rows in the table will match the where clause. When this happens, you typically want to add an index to speed up the sort instead of the where clause.
&lt;/p&gt;
&lt;p&gt;
This query sorts on two fields, &lt;code&gt;priority&lt;/code&gt; and &lt;code&gt;run_at&lt;/code&gt;. We can easily add an index there, but notice the ordering on the sort. It sorts by priority in descending order. Because of the way database indexes work, they are typically only used for ascending order sorts. If you were to create an index on &lt;code&gt;delayed_jobs(priority,run_at)&lt;/code&gt; the database won't be able to use the index. (You can try it out. Add the index and &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.0/en/explain.html&quot;&gt;explain&lt;/a&gt; the query.
&lt;/p&gt;
&lt;p&gt;
Some databases, like Oracle, allow you to create an index with a specified ordering. For example, you can create an index on &lt;code&gt;delayed_jobs(priority desc, run_at asc)&lt;/code&gt; which will then allow the query to use the index. While that syntax is supported by MySQL, the ordering is ignored. That means MySQL still won't be able to use the index.
&lt;/p&gt;
&lt;p&gt; So how did I solve the problem? Simple. I changed the semantics of priority. By default, Delayed Job expects a higher value of priority to be more important. I decided to assign lower numbers to mean more important (similar to &lt;a href=&quot;http://en.wikipedia.org/wiki/Nice_(Unix)&quot;&gt;Unix nice values&lt;/a&gt;.) Once I changed the way I assigned priorities, I simply changed the query to order by &lt;code&gt;priority ASC, run_at ASC&lt;/code&gt; and added an index on &lt;code&gt;delayed_jobs(priority,run_at)&lt;/code&gt;. Now, when the query is run, the log looks like:
&lt;/p&gt;
&lt;code class=&quot;code&quot;&gt;
&lt;pre class=&quot;code&quot;&gt;
# Query_time: 0  Lock_time: 0  Rows_sent: 5  Rows_examined: 5
SELECT * FROM `delayed_jobs` WHERE ((run_at &lt;= '2009-11-04 06:58:49' AND (locked_at IS NULL OR locked_at &lt; '2009-11-04 02:58:49') OR (locked_by = 'host:example.com pid:17731')) AND failed_at IS NULL)  ORDER BY priority ASC, run_at ASC LIMIT 5;
&lt;/pre&gt;
&lt;/code&gt;
&lt;p&gt;
That quickly reduced the load on the system and improved application performance.
&lt;/p&gt;

</description>
          <pubDate>Wed, 04 Nov 2009 06:44:28 GMT</pubDate>
          <guid>http://www.elevatedrails.com/articles/2009/11/04/speeding-up-delayed-job/</guid>
          <link>http://www.elevatedrails.com/articles/2009/11/04/speeding-up-delayed-job/</link>
        </item>
    
        <item>
          <title>Slides from Inman Connect 2009</title>
          <description>&lt;p&gt;As promised, I wanted to provide my slides from &lt;a href=&quot;/InmanMangino.pdf&quot;&gt;Inman Connect 2009&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;My favorite links for learning about Agile methodologies are:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.agilemanifesto.org&quot;&gt;The Agile Manifesto&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.threeriversinstitute.org/blog/&quot;&gt;Kent Beck&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://alistair.cockburn.us/Characterizing+people+as+non-linear%2c+first-order+components+in+software+development&quot;&gt;Cockburn on people as non-linear, first-order components&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.poppendieck.com/publications.htm&quot;&gt;Lean principals applied to software&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are many more, but those are some of my favorites.&lt;/p&gt; </description>
          <pubDate>Tue, 11 Aug 2009 06:42:45 GMT</pubDate>
          <guid>http://www.elevatedrails.com/articles/2009/08/11/slides-from-inman-connect-2009/</guid>
          <link>http://www.elevatedrails.com/articles/2009/08/11/slides-from-inman-connect-2009/</link>
        </item>
    
        <item>
          <title>Standing up to be counted</title>
          <description>&lt;p&gt;Nick Sieger &lt;a href=&quot;http://blog.nicksieger.com/articles/2009/04/30/stand-and-be-counted&quot;&gt;asked that people stand and be counted&lt;/a&gt; and I too will join in. I&amp;#8217;m disappointed with many in our community. While I think the presentation that sparked this discussion was in poor taste, it&amp;#8217;s not the presentation that bothers me. I&amp;#8217;m disappointed by how little empathy some people are showing.&lt;/p&gt;
&lt;p&gt;Whether you agree with somebody or not, I think it&amp;#8217;s important to try to see things from their perspective. It may not change your mind, but it will hopefully at least give you a better understanding of how your actions affect others.&lt;/p&gt; </description>
          <pubDate>Thu, 30 Apr 2009 09:58:57 GMT</pubDate>
          <guid>http://www.elevatedrails.com/articles/2009/04/30/standing-up-to-be-counted/</guid>
          <link>http://www.elevatedrails.com/articles/2009/04/30/standing-up-to-be-counted/</link>
        </item>
    
        <item>
          <title>Speeding up location based searches</title>
          <description>&lt;p&gt;
With the popularity of &lt;a href=&quot;http://maps.google.com&quot;&gt;Google Maps&lt;/a&gt;, more and more web applications are becoming location aware. Rails already has some great tools for working with geodata, such as &lt;a href=&quot;http://github.com/andre/geokit-gem/tree/master&quot;&gt;GeoKit&lt;/a&gt;. We've been happily using these tools for years. While GeoKit has some basic optimizations, we recently found a case where lookups were taking close to 8 seconds. We needed a way to speed this up. Read on to learn how we did it.
&lt;/p&gt; &lt;p&gt;
 First, let me explain our domain. We are working on a site that shows the 25 nearest amenities to a location. The application is focused on San Francisco and the surrounding areas. We store the amenities in a table with columns for latitude and longitude. All told, we search about 800,000 amenity records.
&lt;/p&gt;
&lt;p&gt;
To find the nearest 25 amenities, our database has to do a lot of work. For each listing in the database, we need to &lt;a href=&quot;http://en.wikipedia.org/wiki/Haversine_formula&quot;&gt;calculate the distance&lt;/a&gt; from our origin. Performing that calculation would be unbearably slow, so geokit speeds up the query by including a square bounds. First, the list of locations is limited by a square 5 miles on a side (we use a big window to make sure we get amenities in more rural areas.) Once we've limited  our dataset, the results are sorted by distance. Unfortunately, due to the amenity density in San Francisco, we still have to go through 10,000 records on average.
&lt;/p&gt;
&lt;p&gt;
This calculation and sort is just slow. In version 5.1, MySQL includes some geospatial extensions. These extensions include datatypes for locations and spatial indexes to make spatial searches much faster. Unfortunately, ActiveRecord doesn't support these extensions. That means we'll have to do some things manually.
&lt;/p&gt;
&lt;p&gt;

First, let's look at the three primitives we'll use. The first is a @Point@. Points represent a location in a 2D space. We'll use Points to represent the location of an amenity by it's latitude and longitude coordinates. In MySQL, you can create a point using the SQL: @GeomFromText('Point(38.567 -122.576)')@ 
&lt;/p&gt;
&lt;p&gt;

The second primitive is a @Polygon@. Polygons include a list of coordinates that make up the vertices. Polygons must be closed. For example, we could create the polygon @GeomFromText('Polygon((0 0,0 1,1 1,1 0,0 0))')@. We'll use a Polygon to represent the boundary inside which we want to search.
&lt;/p&gt;
&lt;p&gt;

The final primitive is a @Line@. We use a Line to calculate the distance between two points. According to the OpenGIS specification, we should be able to use the distance function for this. Unfortunately, MySQL doesn't implement Distance.
&lt;/p&gt;
&lt;p&gt;

We'll also need to create a spatial index. A spatial index is an r-tree index that is optimized for fast distance calculations. Currently, only MyISAM tables support spatial indexes. They also require that the column be defined as NOT NULL. We'll have to keep that in mind as we go along.
&lt;/p&gt;
&lt;p&gt;

Let's start by adding a Point column to our amenities table. Because ActiveRecord doesn't support the GIS extensions, we'll need to use the execute method inside our migration. This looks like:
&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
    execute &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;alter table amenities add lat_lng_point point not null&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;

Because we want to use Spatial indexes, we'll also need to convert our amenities table to MyISAM. 
&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
    execute &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;alter table amenities engine myisam&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;

With that in place, we'll need to convert our existing data to include the @lat_lng_point@ column. From what I can tell, Points can only be created using the GeomFromText method. That means we'll need to generate the text representation of a Point during our conversion. This can be done with the following SQL&quot;
&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;update&lt;/span&gt; &lt;span style=&quot;&quot;&gt;amenities&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;set&lt;/span&gt; &lt;span style=&quot;&quot;&gt;lat_lng_point&lt;/span&gt; = &lt;span style=&quot;&quot;&gt;GeomFromText&lt;/span&gt;(&lt;span style=&quot;&quot;&gt;concat&lt;/span&gt;(&lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;Point(&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;span style=&quot;&quot;&gt;lat&lt;/span&gt;,&lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;span style=&quot;&quot;&gt;lng&lt;/span&gt;,&lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;))
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;

At this point, we now have a table with the location data being stored as a Point. Since all of our records have a Point, we now meet the criteria for adding our spatial index:
&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
    execute &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;create spatial index amenities_spatial_idx on amenities(lat_lng_point)&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;

With that in place, we can need a method that does a few thing. First, we need to compute a bounds to limit our distance calculation. We'll do that using @GeoKit::Bounds@. Once we have that, we need to write a query that uses the @MBRWithin@ function (MBR stands for Minimum Bounding Rectangle) to find the list of points inside our Bounds. Once we have that, we can use a Line to get the distance between our origin and each point and order by that. The end result is a little ugly:
&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
  
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#038;font-weight:bold&quot;&gt;self&lt;/span&gt;.near(mappable)
    bound = &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;GeoKit&lt;/span&gt;::&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Bounds&lt;/span&gt;.from_point_and_radius(mappable,&lt;span style=&quot;color:#00D;font-weight:bold&quot;&gt;5&lt;/span&gt;)
    sql = &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;lt;&amp;lt;SQL&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;&quot;&gt;
    select *,  GLength(LineStringFromWKB(LineString(AsBinary(lat_lng_point), 
    (AsBinary(GeomFromText('Point(&lt;/span&gt;&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;#{&lt;/span&gt;mappable.lat&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;#{&lt;/span&gt;mappable.lng&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;)')))))) * 69 as distance
    from amenities where MBRWithin(lat_lng_point,
     GeomFromText('Polygon((&lt;/span&gt;&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;#{&lt;/span&gt;bound.ne.lat&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;#{&lt;/span&gt;bound.ne.lng&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;#{&lt;/span&gt;bound.ne.lat&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;#{&lt;/span&gt;bound.sw.lng&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;#{&lt;/span&gt;bound.sw.lat&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;#{&lt;/span&gt;bound.sw.lng&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;#{&lt;/span&gt;bound.sw.lat&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;#{&lt;/span&gt;bound.ne.lng&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;#{&lt;/span&gt;bound.ne.lat&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;#{&lt;/span&gt;bound.ne.lng&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;))')) 
    order by distance asc limit 25;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;
SQL&lt;/span&gt;&lt;/span&gt;
    find_by_sql(sql)
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;

It's ugly, but it is blazingly fast! Our query went from 8s to 0.01s. That's definitely worth a little code ugliness. 
&lt;/p&gt;
&lt;p&gt;

While we've handled the inital data conversion and querying, we can't add data to our table. We need to provide a Point for each record, and there's no way to do that using ActiveRecord. Instead, we'll need to use a MySQL trigger.
&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
    execute &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;lt;&amp;lt;EOT&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;&quot;&gt;
      create trigger set_lat_lng_point 
      before insert on amenities for each row 
      set  new.lat_lng_point = GeomFromText(concat('Point(',new.lat,' ',new.lng,')'));&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;
EOT&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;

That code will create a Point from the lat and lng when a record is inserted. If you need to be able to update locations, you could make the trigger fire on update as well. You'll want to install the &lt;a href=&quot;http://artriggers.rubyforge.org/&quot;&gt;Trigger Happy&lt;/a&gt; plugin so that your triggers are dumped and included in your test database.
&lt;/p&gt;
&lt;p&gt;

After all that, can you believe we're still not quite done? Due to a bug in MySQL, inserting a row where @lat_lng_point@ is NULL will give an error. It turns out that MySQL checks the not null columns before triggers are run. Luckily, there is a workaround. If you don't explicitly set the column value to NULL, the trigger will be run before the value is checked. To get ActiveRecord to not explicitly set the column to NULL, we'll use a bit of a hack.
&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
  &lt;span style=&quot;color:#888&quot;&gt;# Remove lat_lng_point from the list of attributes&lt;/span&gt;
  &lt;span style=&quot;color:#888&quot;&gt;# otherwise, AR writes it as NULL which keeps the trigger from firing&lt;/span&gt;
  &lt;span style=&quot;color:#888&quot;&gt;# and setting the value correctly  &lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;before_save&lt;/span&gt;
    &lt;span style=&quot;color:#33B&quot;&gt;@attributes&lt;/span&gt;.delete(&lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;lat_lng_point&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;

That code will remove the column for AR's list of attributes. 
&lt;/p&gt;
&lt;p&gt;

Obviously, this is somewhat complicated. If your searches are running okay using just normal SQL, I wouldn't recommend changing. If you need high performance and are searching large amounts of data, this little bit of code can make a huge difference.
&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
&lt;span style=&quot;color:#888&quot;&gt;# Our entire migration&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;ConvertAmenitiesToUseSpatials&lt;/span&gt; &amp;lt; &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Migration&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#038;font-weight:bold&quot;&gt;self&lt;/span&gt;.up
    execute &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;alter table amenities add lat_lng_point point not null&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
    execute &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;alter table amenities engine myisam&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
    execute &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;update amenities set lat_lng_point = GeomFromText(concat(&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;Point(&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;,lat,&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\'&lt;/span&gt;&lt;span style=&quot;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;,lng,&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
    execute &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;create spatial index amenities_spatial_idx on amenities(lat_lng_point)&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
    execute &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;create trigger set_lat_lng_point before insert on amenities for each row set  new.lat_lng_point = GeomFromText(concat('Point(',new.lat,' ',new.lng,')'));&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#038;font-weight:bold&quot;&gt;self&lt;/span&gt;.down
    execute &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;alter table amenities drop lat_lng_point&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

</description>
          <pubDate>Fri, 06 Mar 2009 06:35:51 GMT</pubDate>
          <guid>http://www.elevatedrails.com/articles/2009/03/06/speeding-up-location-based-searches/</guid>
          <link>http://www.elevatedrails.com/articles/2009/03/06/speeding-up-location-based-searches/</link>
        </item>
    
        <item>
          <title>Speeding up SOLR indexing</title>
          <description>&lt;p&gt; We're finishing up a project that uses SOLR and &lt;a href=&quot;http://acts-as-solr.rubyforge.org/&quot;&gt;acts_as_solr&lt;/a&gt; extensively. Our dataset isn't large, but it's non-trivial as well. We're managing a search index with a little over 100,000 documents in it. Each document has indexes on 12 fields. In general, our search performance is outstanding. We get results almost instantly. Our indexing performance was another story. I'm not a big fan of premature optimization, but when a full reindex took 4 days, I decided something needed to change&lt;/p&gt; &lt;p&gt;
  There's some &lt;a href=&quot;http://blog.aisleten.com/2008/01/26/optimizing-solr-and-rails-index-in-the-background/&quot;&gt;good advice&lt;/a&gt; on the web for pulling indexing out of a request flow. Unfortunately for us, this wasn't going to help. Our updates would take several days to process. This delay makes testing changes to search incredibly painful.
&lt;/p&gt;
&lt;p&gt;After much googling, I found a number of people that recommended allowing SOLR to manage its own commits. It took me a few tries to get this working. In the end, I was making it much harder than it had to be. Disabling autcommit really only takes two steps.
&lt;/p&gt;
&lt;p&gt;
 First, update your call to &lt;code&gt;acts_as_solr&lt;/code&gt; to disable autcommit:
&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;MyIndexedModel&lt;/span&gt; &amp;lt; &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Base&lt;/span&gt;
  acts_as_solr &lt;span style=&quot;color:#A60&quot;&gt;:fields&lt;/span&gt;=&amp;gt;[&lt;span style=&quot;color:#A60&quot;&gt;:name&lt;/span&gt;,&lt;span style=&quot;color:#A60&quot;&gt;:body&lt;/span&gt;], &lt;span style=&quot;color:#A60&quot;&gt;:auto_commit&lt;/span&gt;=&amp;gt;&lt;span style=&quot;color:#038;font-weight:bold&quot;&gt;false&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
  With just that change our index performance went from 2 seconds per record to 50 records per second. A 100x speed up. Unfortunately, our changes weren't showing up in the index. SOLR doesn't add indexed records to the database until a commit is done. SOLR does provide an easy way to tell it to manage the commits itself. To enable this, edit &lt;code&gt;vendor/plugins/acts_as_solr/solr/solr/conf/solrconfig.xml&lt;/code&gt;. There is commented out configuration for &lt;code&gt;autoCommit&lt;/code&gt;. Remove the XML comments around this area. We use the &lt;code&gt;maxTime&lt;/code&gt; parameter to have SOLR update the index every minute. Our configuration looks like:
&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
...
  &lt;span style=&quot;color:#070&quot;&gt;&amp;lt;updateHandler&lt;/span&gt; &lt;span style=&quot;color:#007&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;solr.DirectUpdateHandler2&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#070&quot;&gt;&amp;gt;&lt;/span&gt;

    &lt;span style=&quot;color:#888&quot;&gt;&amp;lt;!-- A prefix of &amp;quot;solr.&amp;quot; for class names is an alias that
         causes solr to search appropriate packages, including
         org.apache.solr.(search|update|request|core|analysis)
     --&amp;gt;&lt;/span&gt;

    &lt;span style=&quot;color:#070&quot;&gt;&amp;lt;autoCommit&amp;gt;&lt;/span&gt;
      &lt;span style=&quot;color:#070&quot;&gt;&amp;lt;maxDocs&amp;gt;&lt;/span&gt;10000&lt;span style=&quot;color:#070&quot;&gt;&amp;lt;/maxDocs&amp;gt;&lt;/span&gt;
      &lt;span style=&quot;color:#070&quot;&gt;&amp;lt;maxTime&amp;gt;&lt;/span&gt;60000&lt;span style=&quot;color:#070&quot;&gt;&amp;lt;/maxTime&amp;gt;&lt;/span&gt;
    &lt;span style=&quot;color:#070&quot;&gt;&amp;lt;/autoCommit&amp;gt;&lt;/span&gt;
...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
 That's all there is to it! We get 100x faster indexing and our updates still show up within a minute. Suddenly I don't dread making changes to our indexed models!
&lt;/p&gt;</description>
          <pubDate>Wed, 14 Jan 2009 12:01:01 GMT</pubDate>
          <guid>http://www.elevatedrails.com/articles/2009/01/14/speeding-up-solr-indexing/</guid>
          <link>http://www.elevatedrails.com/articles/2009/01/14/speeding-up-solr-indexing/</link>
        </item>
    
        <item>
          <title>Announcing Facebooker support for Facebook Connect</title>
          <description>&lt;p&gt;
  Over the last few months I've received quite a few requests for Facebook Connect support in Facebooker. Thanks to Kevin Lochner, I'm proud to announce Facebook Connect support in Facebooker. Read on to learn how to create a simple Facebook Connect application.
&lt;/p&gt;
 &lt;p&gt;
  
&lt;/p&gt;
&lt;p&gt;
  The setup of a Facebook Connect application is very similar to that of a Facebook Platform Application. You'll need to create an application using the Facebook Developer tool and then build a Rails application and install the Facebooker plugin. If you need help with this, check out &lt;a href=&quot;http://www.pragprog.com/screencasts/v-mmfacer/rails-development-for-the-facebook-platform&quot;&gt;the screencast&lt;/a&gt; or &lt;a href=&quot;http://www.pragprog.com/titles/mmfacer&quot;&gt;My Book&lt;/a&gt;. You'll need to set up your facebooker.yml and configure a callback URL on Facebook.
&lt;/p&gt;
&lt;p&gt;
  Once you've got a basic application set up and running, we'll need to generate an &lt;code&gt;xd_receiver&lt;/code&gt; file. The xd_receiver file allows Facebook to perform cross domain javascript requests. You can generate this file by running:
&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
  script/generate xd_receiver
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
  A file named &lt;code&gt;xd_receiver.html&lt;/code&gt; will be generated and placed in your &lt;code&gt;public&lt;/code&gt; directory. Make sure this file is added to your source code control system. It must exist for Facebook Connect to work.
&lt;/p&gt;
&lt;p&gt;
  With that setup done, it's time to try out Facebook Connect. Before we can do anything else, we'll need to ask our user to login. Let's create a controller and an action for testing. I called my controller &quot;connect&quot; and just used the index action because I'm lazy. Inside the view for action, we'll need to include a javascript file and do a little setup. Add this to your view:
&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
&lt;span style=&quot;color:#34b&quot;&gt;&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Strict//EN&amp;quot; &amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color:#070&quot;&gt;&amp;lt;html&lt;/span&gt; &lt;span style=&quot;color:#007&quot;&gt;xmlns&lt;/span&gt;=&lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;http://www.w3.org/1999/xhtml&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#007&quot;&gt;xmlns:fb&lt;/span&gt;=&lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;http://www.facebook.com/2008/fbml&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#070&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color:#070&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;&amp;lt;%=&lt;/span&gt; javascript_include_tag &lt;span style=&quot;color:#A60&quot;&gt;:defaults&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;color:#070&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color:#070&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color:#070&quot;&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;My Great Application&lt;span style=&quot;color:#070&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;&amp;lt;%=&lt;/span&gt; fb_connect_javascript_tag &lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;&amp;lt;%=&lt;/span&gt; init_fb_connect &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;XFBML&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;&amp;lt;%=&lt;/span&gt; fb_login_button&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#070&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color:#070&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
  Facebook connect requires an XHTML doctype declaration along with a namespace on your HTML element. It also works most reliably if your HTML is valid. If you're getting strange results, it's worth validating your HTML. The three calls to helpers are the actual meat of the view. The first call includes the Facebook Connect javascript. The second line runs a little setup and the final line renders an &amp;lt;fb:login-button&amp;gt; tag. 
&lt;/p&gt;
&lt;p&gt;
  If all goes well, you should see something that looks like:
 &lt;img src=&quot;/images/fb_connect_1.png&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  If you don't see that, you'll need to verify that things are configured just right. There's a lot of magic going on and it tends to be brittle. Make sure that your callback URL is correctly set and that you are accessing your site using the callback URL. Make sure that your &lt;code&gt;public/xd_receiver.html&lt;/code&gt; file exists. Finally, make sure that you have correctly set up your facebooker.yml file.
&lt;/p&gt;
&lt;p&gt;
 Take a look at the source of your page. Doesn't that &amp;lt;fb:login-button&amp;gt; tag look strange? To render &lt;a href=&quot;http://wiki.developers.facebook.com/index.php/XFBML&quot;&gt;FBML&lt;/a&gt; inside your page, Facebook is using into the HTML equivalents. The login button is just one of many tags we can use. For example, we can include a user's profile photo by calling &lt;code&gt;fb_profile_pic&lt;/code&gt;. Add a call to show your own profile. Once you've done that, you should see something like:
 &lt;img src=&quot;/images/fb_connect_1.png&quot; /&gt;
Notice that Facebook isn't showing your picture. That's because of privacy restrictions. Before we can see information about a Facebook user, we'll need to login. Click the &quot;connect&quot; button and you should see a popup prompting you to log in. After logging in, your profile picture will now be shown.
&lt;/p&gt;
&lt;p&gt;
  Getting access to FBML outside of the Facebook canvas is cool, but it's just a start to what we can do. When we login using Facebook Connect, Facebook sets several cookies that our application can use to access a Facebook session. Facebooker knows how to use these cookies to set up a facebook session. Add the following code to your controller:
&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
  before_filter &lt;span style=&quot;color:#A60&quot;&gt;:set_facebook_session&lt;/span&gt;
  helper_method &lt;span style=&quot;color:#A60&quot;&gt;:facebook_session&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
 That code sets up the users Facebook session and makes it available to the view. With it, you have access to the normal REST API as you can see in the following code.
&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; facebook_session &lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span style=&quot;color:#070&quot;&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;You are logged in as &lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;&amp;lt;%=&lt;/span&gt; facebook_session.user.name &lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#070&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt; &lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span style=&quot;color:#070&quot;&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;You are not logged in!&lt;span style=&quot;color:#070&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
This means you can ask for data about a user like their name and their friends. You can also post stories to their feed! You have most of the power of a Facebook Platform application inside your existing code!
&lt;/p&gt;
&lt;p&gt;
  This support is still very new, so make sure you join the Facebooker mailing list on Rubyforge if you decide to use it. Let us know what you build with it!
&lt;/p&gt;
&lt;p&gt;
  Thanks again to Kevin Lochner who provided the patch to support authentication using cookies. Thanks also to Nate Kontny of &lt;a href=&quot;http://www.inklingmarkets.com&quot;&gt;Inkling Markets&lt;/a&gt; who provided a great overview of how Facebook Connect works! Happy New Year everyone!
&lt;/p
</description>
          <pubDate>Fri, 02 Jan 2009 09:51:20 GMT</pubDate>
          <guid>http://www.elevatedrails.com/articles/2009/01/02/announcing-facebooker-support-for-facebook-connect/</guid>
          <link>http://www.elevatedrails.com/articles/2009/01/02/announcing-facebooker-support-for-facebook-connect/</link>
        </item>
    
        <item>
          <title>Daemonizing Rails</title>
          <description>&lt;p&gt;No, this isn't a post about us converting from Linux to BSD. Instead, I'm talk about starting long running processes that use the Rails environment. If you've tried to do this, you've probably seen some obscure errors like:
&lt;/p&gt;
&lt;pre&gt;
closed stream 
activesupport-2.1.0/lib/active_support/buffered_logger.rb:105:in `write'
activesupport-2.1.0/lib/active_support/buffered_logger.rb:105:in `flush'
activesupport-2.1.0/lib/active_support/buffered_logger.rb:118:in `auto_flush'
activesupport-2.1.0/lib/active_support/buffered_logger.rb:70:in `add'
activesupport-2.1.0/lib/active_support/buffered_logger.rb:76: ...
&lt;/pre&gt;
&lt;p&gt;
Inside, I'll show you how to avoid this
&lt;/p&gt; &lt;p&gt;
Daemons in UNIX are a wonderful, magical thing. Even though it seems like starting up a background job should be simple, there are a lot of steps involved. You can see them in detail in &lt;a href=&quot;http://tammersaleh.com/system/assets/angels_and_daemons.pdf&quot;&gt;Tammer Saleh's Angels and Daemons talk&lt;/a&gt;. The really interesting issue for us is that processes close all open IO streams when they daemonize. That may not cause a problem for a normal Ruby Application, but it violates some assumptions that Rails makes.
&lt;/p&gt;
&lt;p&gt;
 When Rails boots, it opens a few different file descriptors. First, it opens a log file. This is your production.log or similar. It also makes a connection to the database. Rails gets unhappy when these files are closed out from under it. You could write a lot of code to handle these conditions or you can take the simple way out: Delay booting Rails until after you daemonize. Here's a simple script that does that:
&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
&lt;span style=&quot;color:#34b&quot;&gt;#!/usr/bin/env ruby&lt;/span&gt;
require &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;rubygems&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
require &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;daemons&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ROOT&lt;/span&gt; = &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;File&lt;/span&gt;.expand_path(&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;File&lt;/span&gt;.dirname(&lt;span style=&quot;color:#038;font-weight:bold&quot;&gt;__FILE__&lt;/span&gt;)+&lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;/../&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Daemons&lt;/span&gt;.run_proc(&lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;&quot;&gt;watcher&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:dir_mode&lt;/span&gt; =&amp;gt; &lt;span style=&quot;color:#A60&quot;&gt;:normal&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:dir&lt;/span&gt;=&amp;gt;&lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ROOT&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;/log/&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,&lt;span style=&quot;color:#A60&quot;&gt;:log_output&lt;/span&gt; =&amp;gt;&lt;span style=&quot;color:#038;font-weight:bold&quot;&gt;true&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:backtrace&lt;/span&gt;=&amp;gt;&lt;span style=&quot;color:#038;font-weight:bold&quot;&gt;true&lt;/span&gt;) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  require &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ROOT&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;/config/environment&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span style=&quot;color:#888&quot;&gt;# Do work here&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
This code is simple, but there are a couple of subtleties. The first is that we need to use &lt;code&gt;File.expand_path&lt;/code&gt; to turn the Rails Root path into an absolute path. When an application daemonizes, it changes its working directory to &quot;/&quot;. If we use a relative path for our RAILS_ROOT it will no longer point to our Rails installation.
&lt;/p&gt;
&lt;p&gt;
Once we have the absolute RAILS_ROOT path, we can daemonize and then boot Rails. Rails will now start as usual and all files will be opened. That's all there is to it. Now you can easily start long running processes using Rails. You can even use a cap task to easily restart them on deploy:
&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;
task &lt;span style=&quot;color:#A60&quot;&gt;:restart_watcher&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  run &lt;span style=&quot;background-color:#fff0f0;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;background:#eee;color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;#{&lt;/span&gt;current_path&lt;span style=&quot;font-weight:bold;color:#777&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;/script/watcher restart&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

</description>
          <pubDate>Tue, 02 Dec 2008 12:02:54 GMT</pubDate>
          <guid>http://www.elevatedrails.com/articles/2008/12/02/daemonizing-rails/</guid>
          <link>http://www.elevatedrails.com/articles/2008/12/02/daemonizing-rails/</link>
        </item>
    
        <item>
          <title>It feels good to see your name in print</title>
          <description>&lt;p&gt;It was almost a full year ago that I started writing a &lt;a href=&quot;http://www.pragprog.com/titles/mmfacer&quot;&gt;book on Facebook development.&lt;/a&gt; This past Friday I got a very exciting box. Unboxing pictures inside.&lt;/p&gt; &lt;p&gt;&lt;img src=&quot;/unboxing_1.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;A nice note on top of the box.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/unboxing_2.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Carefully wrapped&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/unboxing_3.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;There it is.&lt;/p&gt;
&lt;p&gt;I really underestimated the amount of work it would take to write a book. I had read Dave Thomas&amp;#8217; &lt;a href=&quot;http://pragdave.pragprog.com/pragdave/2007/03/sywtwab_1_so_yo.html&quot;&gt;So You Want to Write a Book&lt;/a&gt; so I should have realized what an undertaking it was. I had just completed my first marathon at that point and figured it couldn&amp;#8217;t be harder than running 26.2 miles. Boy was I ever wrong. I&amp;#8217;m proud of the book. I know it is something I would have loved to have when starting to develop Facebook applications.&lt;/p&gt;
&lt;p&gt;Now I&amp;#8217;m going to get back to training for the Philly Marathon on 11/23. Training seems much easier now.&lt;/p&gt;</description>
          <pubDate>Wed, 22 Oct 2008 08:11:51 GMT</pubDate>
          <guid>http://www.elevatedrails.com/articles/2008/10/22/it-feels-good-to-see-your-name-in-print/</guid>
          <link>http://www.elevatedrails.com/articles/2008/10/22/it-feels-good-to-see-your-name-in-print/</link>
        </item>
    
    
  </channel>
</rss>

