<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>While I Pondered...</title>
	<atom:link href="http://masonoise.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://masonoise.wordpress.com</link>
	<description>Over many a quaint and curious volume of forgotten lore.</description>
	<lastBuildDate>Wed, 22 May 2013 00:22:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='masonoise.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://1.gravatar.com/blavatar/5267747f1bdb6c4d879e5701e7a4ad64?s=96&#038;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>While I Pondered...</title>
		<link>http://masonoise.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://masonoise.wordpress.com/osd.xml" title="While I Pondered..." />
	<atom:link rel='hub' href='http://masonoise.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Sending an S3 object as a Mailgun attachment</title>
		<link>http://masonoise.wordpress.com/2013/05/22/sending-an-s3-object-as-a-mailgun-attachment/</link>
		<comments>http://masonoise.wordpress.com/2013/05/22/sending-an-s3-object-as-a-mailgun-attachment/#comments</comments>
		<pubDate>Wed, 22 May 2013 00:22:28 +0000</pubDate>
		<dc:creator>masonoise</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[mailgun]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[s3]]></category>

		<guid isPermaLink="false">http://masonoise.wordpress.com/?p=230</guid>
		<description><![CDATA[I&#8217;ve recently started using Mailgun, which I like quite a bit, but I stumbled on an issue dealing with attachments, because the files I needed to attach are stored in S3. Using RestClient to send the emails, the expectation is that attachments are files. As it turns out, using the aws-sdk gem, S3 objects don&#8217;t &#8230;<p><a href="http://masonoise.wordpress.com/2013/05/22/sending-an-s3-object-as-a-mailgun-attachment/" class="more-link">Read More</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=230&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>
I&#8217;ve recently started using Mailgun, which I like quite a bit, but I stumbled on an issue dealing with attachments, because the files I needed to attach are stored in S3. Using RestClient to send the emails, the expectation is that attachments are files. As it turns out, using the aws-sdk gem, S3 objects don&#8217;t quite behave like files, so it doesn&#8217;t work to simply toss the S3Object instance into the call.
</p>
<p>
The standard setup for sending an email is like the following:
</p>
<pre class="brush: ruby; title: ; notranslate">
 data = Multimap.new
 data[:from] = &quot;My Self &lt;no-reply@example.com&gt;&quot;
 data[:subject] = &quot;Subject&quot;
 data[:to] = &quot;#{recipients.join(', ')}&quot;
 data[:text] = text_version_of_your_email
 data[:html] = html_version_of_your_email
 data[:attachment] = File.new(File.join(&quot;files&quot;, &quot;attachment.txt&quot;))
 RestClient.post &quot;https://api:#{API_KEY}&quot;\
   &quot;@api.mailgun.net/v2/#{MAILGUN_DOMAIN}/messages&quot;,
   data
</pre>
<p>
As this shows, the attachment is expected to be a File that can be read in. So the challenges was to make an S3 object readable. One option, of course, is to do this in two steps: read in the S3 object and use Tempfile to write a file which can then be used as the attachment. This seemed pretty unfortunate. For one thing, I&#8217;m running stuff on Heroku, and try to avoid using the file system even for temp files. But primarily, it&#8217;s really wasteful to have to write, and then read, a transitory file. The better option, of course, was to see if there was a way to trick the client into reading from S3.
</p>
<p>
Thanks to some very nice help from Mailgun support (thanks Sasha!), the idea of writing a wrapper seemed feasible, and in fact it wasn&#8217;t too bad aside from a couple of tricky issues. A side-effect advantage was that it solved another problem: the naming of the attachment. By default, the name of the attachment is the name of the file, which is pretty ugly if you use a temp file. Not user-friendly.
</p>
<p>
I&#8217;ve put the wrapper file in a <a href="https://gist.github.com/masonoise/5624266">Github Gist at https://gist.github.com/masonoise/5624266</a>. It&#8217;s pretty short, and there were only a couple of gotchas, which I describe below. The key for this wrapper is to provide the methods that RestClient needs: #read, #path, #original_filename, and #content_type. It&#8217;s pretty obvious what #read and #path are for. The attachment naming problem is solved by #original_filename: whatever it returns will be the name of the attachment in the email. It should be clear what #content_type does, but see below for why it&#8217;s important.
</p>
<p>
Using the wrapper is described in the header comment, but it&#8217;s mainly a change to give RestClient the wrapper instead of a File object:
</p>
<pre class="brush: ruby; title: ; notranslate">
data[:attachment] = MailgunS3Attachment.new(file_name, file_key)
</pre>
<p>
The first gotcha was that RestClient calls #read repeatedly for 8124 bytes, and doesn&#8217;t pass a block. This forced me to write a crude sort of buffering &#8212; the wrapper reads the whole S3 object in, then hands out chunks of it when asked. This isn&#8217;t a problem for me because the files I&#8217;m dealing with aren&#8217;t very large, but it&#8217;s something I warn about in the comments. If you have large files, this may be a problem for you, so beware.
</p>
<p>
The second gotcha that threw me off for a little while is that the value returned by #content_type is important. I haven&#8217;t researched exactly why this is, but I found that if I tried to send a Word document but #content_type returns &#8216;text/plain&#8217;, the attachment comes through corrupted. It was easy enough for me to check the filename suffix and set the content type accordingly, but I can imagine cases where this might not work, so this is something else to beware of.
</p>
<p>
Anyway, this solved the issue for me, and hopefully it&#8217;ll be useful for others. There are ways to make this a bit more elegant, but it&#8217;s a short piece of code that works. Enjoy.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/masonoise.wordpress.com/230/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/masonoise.wordpress.com/230/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=230&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://masonoise.wordpress.com/2013/05/22/sending-an-s3-object-as-a-mailgun-attachment/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<georss:point>37.774929 -122.419415</georss:point>
		<geo:lat>37.774929</geo:lat>
		<geo:long>-122.419415</geo:long>
		<media:content url="http://2.gravatar.com/avatar/b6ce020fad75a4b999dbf4f2ae78a6f1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">masonoise</media:title>
		</media:content>
	</item>
		<item>
		<title>pjax and AngularJS</title>
		<link>http://masonoise.wordpress.com/2013/05/01/pjax-and-angularjs/</link>
		<comments>http://masonoise.wordpress.com/2013/05/01/pjax-and-angularjs/#comments</comments>
		<pubDate>Wed, 01 May 2013 05:18:05 +0000</pubDate>
		<dc:creator>masonoise</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[angularjs]]></category>
		<category><![CDATA[pjax]]></category>

		<guid isPermaLink="false">http://masonoise.wordpress.com/?p=221</guid>
		<description><![CDATA[Quick little tip to hopefully save others the hassle of tracking this down&#8230; I just added some pjax to an app in order to quick-load some content into a DIV in the page. However, the content includes a small AngularJS app, and when the content got loaded, the app wasn&#8217;t getting initialized, so instead of &#8230;<p><a href="http://masonoise.wordpress.com/2013/05/01/pjax-and-angularjs/" class="more-link">Read More</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=221&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>
Quick little tip to hopefully save others the hassle of tracking this down&#8230; I just added some <a href="https://github.com/defunkt/jquery-pjax">pjax</a> to an app in order to quick-load some content into a DIV in the page. However, the content includes a small AngularJS app, and when the content got loaded, the app wasn&#8217;t getting initialized, so instead of nice content I had mustache tags {{all over the place}}. Not so nice. After some searching and testing, I found that the following works:
</p>
<pre class="brush: jscript; title: ; notranslate">
    $(document).pjax('a[data-pjax]', '#content-panel');
    $(document).on('pjax:complete', function() {
        angular.bootstrap($(&quot;#content-panel&quot;)[0], [&quot;my-app&quot;]);
    })
</pre>
<p>
That waits for the pjax request to complete, then boots the AngularJS app, and everything is good again.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/masonoise.wordpress.com/221/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/masonoise.wordpress.com/221/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=221&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://masonoise.wordpress.com/2013/05/01/pjax-and-angularjs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<georss:point>37.774929 -122.419415</georss:point>
		<geo:lat>37.774929</geo:lat>
		<geo:long>-122.419415</geo:long>
		<media:content url="http://2.gravatar.com/avatar/b6ce020fad75a4b999dbf4f2ae78a6f1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">masonoise</media:title>
		</media:content>
	</item>
		<item>
		<title>AngularJS Directives</title>
		<link>http://masonoise.wordpress.com/2013/04/18/angularjs-directives/</link>
		<comments>http://masonoise.wordpress.com/2013/04/18/angularjs-directives/#comments</comments>
		<pubDate>Thu, 18 Apr 2013 23:21:42 +0000</pubDate>
		<dc:creator>masonoise</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[angularjs]]></category>

		<guid isPermaLink="false">http://masonoise.wordpress.com/?p=199</guid>
		<description><![CDATA[Last week I started in on learning AngularJS and putting it to work on the app at my new company, FinderLabs. I have a long post coming up detailing what I&#8217;ve learned about setting up an AngularJS page backed by a simple Rails API, but for today I just wanted to jot down some notes &#8230;<p><a href="http://masonoise.wordpress.com/2013/04/18/angularjs-directives/" class="more-link">Read More</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=199&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Last week I started in on learning <a href="http://www.angularjs.org">AngularJS</a> and putting it to work on the app at my new company, FinderLabs. I have a long post coming up detailing what I&#8217;ve learned about setting up an AngularJS page backed by a simple Rails API, but for today I just wanted to jot down some notes about creating an AngularJS directive, because I found it pretty painful figuring it out &#8212; some of the AngularJS docs are quite good, and some of them are lacking. Thankfully there are a lot of examples out there, but I had to look over too many of them to get this working. Note that I&#8217;m only moderately comfortable with JavaScript coding, so your mileage may vary.</p>
<p>So, what I wanted to was really easy with plain old jQuery, but it turned out to be more complicated when AngularJS entered the picture. Inside a list of items, for each item I had a DIV into which I was rendering a line graph, using Flotr2, and I had to pass it the JSON data needed for the charting. Before converting my page to AngularJS, I simply iterated my list in Ruby and called item.json_chart_data for each one, and called Flotr2. Not any more; now I&#8217;m using ng-repeat on a collection of items in my controller scope. What to do? I could in theory stuff the chart data into my items when my API returns them to my controller, but that was overloading the items themselves. So instead, I created a directive that loads the chart data for each item via an AJAX call.</p>
<p>Here&#8217;s the relevant markup from the page:</p>
<pre class="brush: xml; title: ; notranslate">
    &lt;div class=&quot;item-graph&quot; id=&quot;item-graph-{{item.id}}&quot; style=&quot;width: 100px; height: 50px; padding-right: 20px&quot;&gt; 
        &lt;item-graph item=&quot;{{item.id}}&quot;&gt;&lt;/item-graph&gt; 
    &lt;/div&gt;
</pre>
<p>
This defines the DIV that Flotr2 is going to draw into, with the width and height, and then inside it is my directive, &#8220;item-graph&#8221;. I pass the item id into the directive, so that it can make the AJAX call to the server to get the graph data. Now let&#8217;s look at the directive:
</p>
<pre class="brush: jscript; title: ; notranslate">
var app = angular.module('my-app', ['restangular', 'ui.bootstrap']).
  config(function(RestangularProvider) {
    RestangularProvider.setBaseUrl('/api/v1');
})
.controller('MyListCtrl', function($scope, Items) {
  $scope.items = Items;
})
.directive('itemGraph', function($http) {
  return {
    restrict: 'E',
    scope:{
        itemId:'@item'
    },
    link: function(scope, element, attrs) {
      scope.$watch('itemId', function(value) {
          if (value) {
            $http.jsonp(&quot;/items/&quot; + value + &quot;/item_graph_data.json?callback=JSON_CALLBACK&quot;).then(function(response){
              draw_line_graph(document.getElementById('item-graph-' + value), response.data);
            });
          }
        });
    }
  }
});
</pre>
<p>
This is all of the code for the page; I&#8217;ll gloss over the top part since that&#8217;s pretty standard AngularJS stuff. It defines the app, injecting the dependencies. I use <a href="https://github.com/mgonto/restangular/">Restangular</a> for most of the server interaction; it does a really nice job of encapsulating things in a clear, RESTful way. The code configures Restangular with the base URL, since my server-side routes are in the &#8216;/api/v1&#8242; space. Then we define the controller, and use the Items service (see below) to fetch the items. Then we get into the more interesting part: the directive.
</p>
<p>
First, note the name of the directive: &#8220;itemGraph&#8221;. But in the page markup, the tag is &#8220;item-graph&#8221; &#8212; it&#8217;s an irritating inconsistency, but just remember that directive names are &#8220;camel cased&#8221; while the name in your markup is &#8220;snake cased&#8221;. Thus &#8220;item-graph&#8221; in the page matches up with &#8220;itemGraph&#8221; in the code. Whatever. So then in the declaration we inject in the $http service so it can be used later.
</p>
<p>
Directives basically return an object with a couple of important sections. The first is random configuration, of which the <code>restrict</code> is very important, and this caused me more than a few minutes of debugging. I seemed to have everything wired up, but nothing was happening. That&#8217;s because <code>restrict</code> defaults to &#8216;A&#8217;, which specifies that the directive is restricted to attributes. I needed &#8216;E&#8217; for element. This is described in the AngularJS page on directives (<a href="http://docs.angularjs.org/guide/directive">here</a>), but it&#8217;s a long, long way down the page buried in details about compiling and the &#8220;directive definition object&#8221;. Major documentation fail, yes. In any case, don&#8217;t make my mistake; as soon as I added this, it started invoking my code.
</p>
<p>
The second piece needed is the scope, which you can think of as what ties the attributes in your page to your directive. In this case, remember that in my page I specified <code>item="{{item.id}}"</code> in order to pass in the item id. In this scope block we specify <code>itemId:'@item'</code>, which says that we want a binding between the local property &#8216;itemId&#8217; and the attribute &#8216;item&#8217;. The &#8216;@&#8217; indicates a one-way data binding. I highly recommend reading this great <a href="http://onehungrymind.com/angularjs-sticky-notes-pt-2-isolated-scope/">blog post</a> that describes the use of attributes, bindings, and functions. You&#8217;ll be glad you did.
</p>
<p>
Whew, okay, so now we have the directive attached to our element, and we have the attribute bound to a local property so we can use it. How do we use it? Well, it&#8217;s a little complicated, but not too bad. First: think of the link() function as what&#8217;s invoked when the directive is &#8220;activated&#8221; for an element. So in here, we want to take the item id that was passed in, and do something. However, it turns out that you don&#8217;t simply use itemId directly, or (as a normal person might assume) go with attrs.itemId; instead, we have to use our scope, and &#8220;watch&#8221; the property. In fairness, this is because often what you&#8217;re doing is binding your directive to something in the page that can change, such as a form field. Then by watching it, your directive can respond to changes in that attribute. In my case that wasn&#8217;t needed, but I still have to play by the rules. So okay, call <code>scope.$watch()</code> on &#8216;itemId&#8217;, and then write a function to deal with it. Apparently when first loaded, the watch function is called, so then we make sure there is a value (perhaps the directive gets loaded before the DOM is ready? I dunno). If there is, let&#8217;s finally do something.
</p>
<p>
What I wanted to do in my case is make a quick call back to the server, specifying the item id &#8212; which, remember, is now represented by &#8220;value&#8221; since that&#8217;s the parameter name on the watch function. When it returns, it calls <code>draw_line_graph()</code>, another function that sets up Flotr2 and does the drawing. It draws the graph into the DOM element passed in, with the data also passed in.
</p>
<p>
And that&#8217;s it. Seems like a lot of code to do what could be done in a couple of lines before, to be honest, but it&#8217;s packaged and reusable, and easily copied to do more complex things. One last thing; as promised I wanted to include the Items service which is used to get the initial list of items for the page, just in case someone finds it useful. It&#8217;s in another small JS file:
</p>
<pre class="brush: jscript; title: ; notranslate">
var app = angular.module('my-app');

app.factory('Items', function($http, Restangular) {
  var baseItems = Restangular.all('items');
  return baseItems.getList();
});
</pre>
<p>
That&#8217;s all there is to it, using Restangular to get the list. This automagically ends up invoking the server URL &#8216;/api/v1/items&#8217; and returns the JSON response. Restangular is even nicer when you start getting into nested relationships and other more complex needs.
</p>
<p>
I&#8217;ve made some of this generic (&#8220;my-app&#8221; and &#8220;Items&#8221;), since I can&#8217;t get show full details of the app I&#8217;m working on, but hopefully it will also make it easier for this to be used by others. I hope this saves others who are new to AngularJS some of the pain I had in figuring all of this out.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/masonoise.wordpress.com/199/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/masonoise.wordpress.com/199/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=199&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://masonoise.wordpress.com/2013/04/18/angularjs-directives/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<georss:point>37.774929 -122.419415</georss:point>
		<geo:lat>37.774929</geo:lat>
		<geo:long>-122.419415</geo:long>
		<media:content url="http://2.gravatar.com/avatar/b6ce020fad75a4b999dbf4f2ae78a6f1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">masonoise</media:title>
		</media:content>
	</item>
		<item>
		<title>Elasticsearch with Rails and Tire</title>
		<link>http://masonoise.wordpress.com/2012/08/11/elasticsearch-with-rails-and-tire/</link>
		<comments>http://masonoise.wordpress.com/2012/08/11/elasticsearch-with-rails-and-tire/#comments</comments>
		<pubDate>Sat, 11 Aug 2012 05:13:21 +0000</pubDate>
		<dc:creator>masonoise</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[elasticsearch]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[tire]]></category>

		<guid isPermaLink="false">http://masonoise.wordpress.com/?p=194</guid>
		<description><![CDATA[I&#8217;ve recently had the chance and excuse to play with Elasticsearch, after reading good things about it. We&#8217;ve been using Solr with decent success, but it feels like whenever we try to do anything outside the normal index-and-search it&#8217;s more complicated than it should be. The basics are easy thanks to the terrific Sunspot gem, &#8230;<p><a href="http://masonoise.wordpress.com/2012/08/11/elasticsearch-with-rails-and-tire/" class="more-link">Read More</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=194&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve recently had the chance and excuse to play with <a href="http://www.elasticsearch.org">Elasticsearch</a>, after reading good things about it. We&#8217;ve been using Solr with decent success, but it feels like whenever we try to do anything outside the normal index-and-search it&#8217;s more complicated than it should be. The basics are easy thanks to the terrific <a href="http://sunspot.github.com/">Sunspot</a> gem, though. So when I had a small project to prototype that involved indexing PDFs as well as database records, I figured it was a good opportunity to try out Elasticsearch.</p>
<p>I quickly reached for the <a href="https://github.com/karmi/tire/">Tire</a> gem, which is very similar to Sunspot if you&#8217;re using ActiveRecord. Where Sunspot has you include a &#8220;searchable&#8221; block, Tire adds a &#8220;mapping&#8221; block, but the idea is the same &#8212; that&#8217;s where you tell it what fields to index, and how to do it. For each field you can adjust the data type, boost, and more. You can also tack on a &#8220;settings&#8221; block to adjust things like the analyzers.</p>
<p>The documentation for Tire is pretty good, but I found that I made a number of mistakes trying to adapt the instructions on the Elasticsearch site to the Tire way of doing things, so I thought I&#8217;d write up some of the things I learned in hopes that it can help save time for others. Many thanks to the folks on <a href="http://www.stackoverflow.com">StackOverflow</a> who answered my questions and pointed me in the right direction.</p>
<p>One starter suggestion is to configure Tire&#8217;s debugger, which is really convenient because it will output the request being sent to the ES server as a curl command that you can copy and paste into a terminal for testing. Very handy. I added this to my <code>config/environments/development.rb</code> file:</p>
<pre class="brush: ruby; title: ; notranslate">
  Tire.configure do
    logger STDERR, :level =&gt; 'debug'
  end
</pre>
<p>Now on to the model. I&#8217;ll call mine Publication, so inside <code>app/models/publication.rb</code>:</p>
<pre class="brush: ruby; title: ; notranslate">
class Publication &lt; ActiveRecord::Base
  include Tire::Model::Search
  include Tire::Model::Callbacks

  attr_accessible :title, :isbn, :authors, :abstract, :pub_date

  settings :analysis =&gt; {
    :filter  =&gt; {
      :ngram_filter =&gt; {
        :type =&gt; &quot;nGram&quot;,
        :min_gram =&gt; 2,
        :max_gram =&gt; 12
      }
    },
    :analyzer =&gt; {
      :index_ngram_analyzer =&gt; {
        :type  =&gt; &quot;custom&quot;,
        :tokenizer  =&gt; &quot;standard&quot;,
        :filter  =&gt; [&quot;lowercase&quot;, &quot;ngram_filter&quot;]
      },
      :search_ngram_analyzer =&gt; {
        :type  =&gt; &quot;custom&quot;,
        :tokenizer  =&gt; &quot;standard&quot;,
        :filter  =&gt; [&quot;standard&quot;, &quot;lowercase&quot;, &quot;ngram_filter&quot;]
      }
    }
  } do
    mapping :_source =&gt; { :excludes =&gt; ['attachment'] } do
      indexes :id, :type =&gt; 'integer'
      indexes :isbn
      [:title, :abstract].each do |attribute|
        indexes attribute, :type =&gt; 'string', :index_analyzer =&gt; 'index_ngram_analyzer', :search_analyzer =&gt; 'search_ngram_analyzer'
      end
      indexes :authors
      indexes :pub_date, :type =&gt; 'date'
      indexes :attachment, :type =&gt; 'attachment'
    end
  end

  def to_indexed_json
    to_json(:methods =&gt; [:attachment])
  end

  def attachment
    if isbn.present?
      path_to_pdf = &quot;/Users/foobar/Documents/docs/#{isbn}.pdf&quot;
      Base64.encode64(open(path_to_pdf) { |pdf| pdf.read })
    end
  end
end
</pre>
<p>Okay, that&#8217;s a lot of code, so let&#8217;s look things over bit by bit. Naturally the includes at the top are needed to mix-in the Tire methods. There are two includes so that you can include the calls needed for searching without the callbacks if you don&#8217;t need them. The callbacks, though, are what make things work auto-magically when you persist ActiveRecord objects. With those, whenever you call <code>save()</code> on an AR model, the object will be indexed into ES for you.</p>
<p>Next up are two blocks of code: <code>settings</code>, and <code>mapping</code>. The settings block defines a filter, and two analyzers, one for indexing and one for searching. I can&#8217;t claim to be enough of an expert yet to fully explain the ramifications of the filter/analyzer options, so rather than risk confusion I&#8217;ll just note that this code is there to set up the nGram filter and connect it with two analyzers, index and search, which differ slightly in order to ensure that the <a href="http://www.elasticsearch.org/guide/reference/index-modules/analysis/standard-tokenfilter.html">standard filter</a> is included for searching. You may want to play with the nGram&#8217;s min and max settings to get the matching behavior you want. Note that if you don&#8217;t need the nGram filter, you can remove the settings block and let the mapping block stand on its own, in which case the default settings will be used (but you&#8217;ll have to change the mapping entry for the <code>:title</code> and <code>:abstract</code> fields, as described below).</p>
<p>The mapping block is the more interesting one, as it defines the fields and indexing behavior. The first line took me some searching and StackOverflow questioning to figure out. The issue that by default, Elasticsearch will put all of the fields you index into its <code>_source</code> storage. Because I&#8217;m indexing large PDF documents, the result was that a huge Base64-encoded field was being stored. If I wanted to serve the PDFs out of Elasticsearch that might be okay, but that&#8217;s not the plan. The <code>:excludes</code> instruction prevents the <code>attachment</code> field from being stored.</p>
<p>Next are the fields themselves, and I won&#8217;t spend much time on these because the Tire documentation does a fine job of explaining these. The only interesting items are the <code>:attachment</code> field and the entry for <code>:title</code> and <code>:abstract</code> &#8212; that one specifies that for those fields the custom analyzers defined in the settings block should be used. For <code>:attachment</code> it gets a little bit tricky.</p>
<p>When the indexing is performed, the fields themselves are gathered up by calling the method <code>to_indexed_json()</code>. Normally that will just do a <code>to_json()</code> on your model and then collect the fields. But you can also override it, which we do here. You can see that we add in the method <code>attachment()</code>, which is defined below. So the other fields will be JSONized as normal, as well as the output of the <code>attachment()</code> method. The <code>attachment()</code> method itself uses the ISBN number to open the PDF file, which is read and Base64-encoded. The results of that encoding will be included with the other fields and sent to ES for indexing.</p>
<p>Performing the searching is almost too easy, but there was one bit that threw me off initially, which was getting highlighting to work. The search block in my controller looks like this:</p>
<pre class="brush: ruby; title: ; notranslate">
results = Publication.search do
  query { string query_string }
  sort { by :pub_date, 'desc' }
  highlight :title, <img src='http://s1.wp.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> ptions =&gt; { :tag =&gt; &quot;&lt;strong class='highlight'&gt;&quot; }
end
</pre>
<p>I was trying to test the highlighting and was thrown off by the field names being case-sensitive (see <a href="http://stackoverflow.com/questions/11907555/elasticsearch-with-tire-highlight-not-working">my question</a> on StackOverflow), but this now works. The other key is that the highlighted fields are returned separately from the plain fields, which was odd to see. This means that to display the highlighting I have to check for the field:</p>
<pre class="brush: ruby; title: ; notranslate">
results.each do |r|
  r_title = (r.highlight.nil? ? r.title : r.highlight.title[0])
  puts &quot;Title: #{r_title}&quot;
end
</pre>
<p>If the highlighting is present then it&#8217;s used; if not (because the term isn&#8217;t present in that field) then the regular field is used. The other handy thing to note is that you can specify the tag with which to wrap the term. The default is &#8220;&lt;em&gt;&#8221; but I wanted to specify the &#8220;highlight&#8221; CSS class, as is shown here. This is a really convenient feature.</p>
<p>That covers the basics, though it&#8217;s also probably worth sharing just how nice it is to be able to test using curl. For example, I wanted to check how easy it is to have the search call return just a single field (to speed up certain requests), so I tried it first in curl:</p>
<pre class="brush: plain; title: ; notranslate">
curl -XPOST http://localhost:9200/publications/_search\?pretty\=true -d '{
&quot;query&quot;: {&quot;query_string&quot;: {&quot;query&quot;: &quot;Foobar&quot;}},
&quot;fields&quot;: [&quot;title&quot;]
}'
</pre>
<p>That&#8217;s of course assuming that ES is running on your local system on port 9200; if not, adjust accordingly.</p>
<p>There you go. I hope this writeup is helpful to folks getting started and it saves you some time.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/masonoise.wordpress.com/194/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/masonoise.wordpress.com/194/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=194&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://masonoise.wordpress.com/2012/08/11/elasticsearch-with-rails-and-tire/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<georss:point>37.774929 -122.419415</georss:point>
		<geo:lat>37.774929</geo:lat>
		<geo:long>-122.419415</geo:long>
		<media:content url="http://2.gravatar.com/avatar/b6ce020fad75a4b999dbf4f2ae78a6f1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">masonoise</media:title>
		</media:content>
	</item>
		<item>
		<title>Showing Timelines using Timeline-Setter and Rails</title>
		<link>http://masonoise.wordpress.com/2012/05/30/showing-timelines-using-timeline-setter-and-rails/</link>
		<comments>http://masonoise.wordpress.com/2012/05/30/showing-timelines-using-timeline-setter-and-rails/#comments</comments>
		<pubDate>Wed, 30 May 2012 05:44:05 +0000</pubDate>
		<dc:creator>masonoise</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[timeline]]></category>

		<guid isPermaLink="false">http://masonoise.wordpress.com/?p=184</guid>
		<description><![CDATA[Recently we wanted to add a nice-looking timeline view to some data in a web app, and looked around for good Javascript libraries. Perhaps the coolest one is Timeline JS from Verite, but while gorgeous it&#8217;s also super heavyweight, and pretty much demands a page all to itself. We wanted something more economical that could &#8230;<p><a href="http://masonoise.wordpress.com/2012/05/30/showing-timelines-using-timeline-setter-and-rails/" class="more-link">Read More</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=184&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Recently we wanted to add a nice-looking timeline view to some data in a web app, and looked around for good Javascript libraries. Perhaps the coolest one is <a href="http://timeline.verite.co/">Timeline JS</a> from Verite, but while gorgeous it&#8217;s also super heavyweight, and pretty much demands a page all to itself. We wanted something more economical that could share the page with some other views, and decided on <a href="http://propublica.github.com/timeline-setter/">Timeline-Setter</a>, which creates pretty little timelines with just enough view area to provide important information about each event.</p>
<p>However, as-provided, Timeline-Setter wants to exist as a command-line utility. You get a data file ready, run the utility, and it generates a set of HTML (and associated) files that you can drop into an app. That&#8217;s dandy if you have a set of data that doesn&#8217;t change often, or you want to perhaps run a cron to pre-generate a bunch of timelines. We needed something that could generate a timeline for a dynamic set of data, so we weren&#8217;t sure Timeline-Setter would work for us. However, looking it over I thought it seemed potentially usable in a dynamic way. I generated a static example using our data, read through what it had created, and deconstructed what it wanted in order to display the timeline, then wrote some code to dynamically generate the JSON data necessary. It wasn&#8217;t too difficult, and fairly shortly we had dynamic timelines going. I wanted to share the info here since it&#8217;s a pretty nice library that others should get a lot out of.</p>
<p>We&#8217;re using <a href="http://documentcloud.github.com/jammit/">Jammit</a> to handle our static assets, so we simply put &#8220;public/javascripts/timeline-setter.js&#8221; and &#8220;public/stylesheets/timeline-setter.css&#8221; into our assets.yml file, but you can use whatever standard approach you take to including JS and CSS into your pages. Once that&#8217;s done, you&#8217;re ready to go.</p>
<p>Timeline-Setter takes a pretty standard approach to placing itself in the page: it takes the ID of a DIV, and that&#8217;s the container which will hold the timeline. One note: we needed to include multiple timelines in a single page, so we had to do a little creative naming of the DIVs that hold the timelines, as you&#8217;ll see below.</p>
<pre class="brush: plain; title: ; notranslate">
&lt;div id=&quot;timeline-&lt;%= author.id %&gt;&quot; class=&quot;timeline_holder&quot;&gt;&lt;/div&gt;
&lt;pre&gt;
&lt;script type=&quot;text/javascript&quot;&gt;// &lt;![CDATA[
    $(function () {
      var currentTimeline = TimelineSetter.Timeline.boot([&lt;%= author.make_timeline_json %&gt;], {&quot;container&quot;:&quot;#timeline-&lt;%= author.id %&gt;&quot;, &quot;interval&quot;:&quot;&quot;, &quot;colorReset&quot;:true});
    });

// ]]&gt;&lt;/script&gt;
</pre>
<p>The code here creates the DIV, gives it an ID, and then places a Javascript call to the Timeline-Setter boot() function, which tells it to generate the timeline. The first parameter is the JSON holding the data for the timeline; the second is a set of options, passed in as JSON. &#8220;container&#8221; of course is the ID of the DIV which will contain the timeline. Other options include &#8220;interval&#8221;, &#8220;formatter&#8221;, and &#8220;colorReset&#8221; among others. See the library&#8217;s page as listed at the beginning for details of the API, and in particular see the section headed &#8220;Configuring the Timeline JavaScript Embed&#8221; for the basics of calling the boot() function.</p>
<p>Now of course we need the make_timeline_json() method, which will take our object&#8217;s data and create the JSON needed by Timeline-Setter. As an example here, let&#8217;s pretend that we&#8217;re showing a timeline of books written by an author over the years.</p>
<pre class="brush: ruby; title: ; notranslate">
class Author &lt; ActiveRecord::Base
  def make_timeline_json
    timeline_list = []
    if (!birth_date.nil?)
      timeline_list &lt;&lt; &quot;{'html':'','date':'#{birth_date}','description':'Birth Date:','link':'','display_date':'','series':'Events','timestamp':#{(birth_date.to_time.to_i * 1000)}}&quot;
    end
    books.each do |book|
      author_list = book.authors.map { |auth| &quot;#{auth['name']}&quot; }.join('; ')
      timeline_list &lt;&lt; &quot;{'html':'Authors: #{author_list}
Publisher: #{book.publisher}','date':'#{book.pub_date}','description':'#{book.title}','link':'','display_date':'','series':'Publications','timestamp':#{(book.pub_date.to_time.to_i * 1000)}}&quot;
    end
    if (!death_date.nil?)
      timeline_list &lt;&lt; &quot;{'html':'','date':'#{death_date}','description':'Death Date:','link':'','display_date':'','series':'Events','timestamp':#{(death_date.to_time.to_i * 1000)}}&quot;
    end
    return &quot;#{timeline_list.join(',')}&quot;
  end
end
</pre>
<p>Essentially, this method creates a JSON string containing a set of entries, each representing an event to place on the timeline. Each entry has several fields: html, date, description, link, display_date, series, and timestamp. Not all of these are used here, but with the basics you can experiment further. The important fields are:</p>
<ul>
<li>html: This will be displayed in the event&#8217;s pop-up when clicked on.</li>
<li>description: Just what it says.</li>
<li>link: an optional URL which will be associated with a link in the event pop-up.</li>
<li>series: which &#8220;series&#8221; this event belongs to; see below for details on this.</li>
<li>timestamp: This is the timestamp associated with the event, used to construct the timeline in order.</li>
</ul>
<p>A note about the &#8220;series&#8221; parameter: one very nice feature of Timeline-Setter is that you can display more than one set of events in a single timeline. Each set of events is called a &#8220;series&#8221;. In our example we&#8217;re creating two series: &#8220;Events&#8221; and &#8220;Publications&#8221;. Each will be shown in a different color, with a title (so the names of the series need to look nice, as they&#8217;ll be displayed) and a checkbox so that a viewer can hide and show each series individually. It&#8217;s extremely useful.</p>
<p>In the code above, you&#8217;ll see that we create the &#8220;Birth Date&#8221; and &#8220;Death Date&#8221; events individually, but in the middle we iterate over the books associated with this author. For each book we build a string of authors, semicolon-delimited, just to demonstrate one way to include another list of information in an event&#8217;s HTML. I have to admit that I&#8217;m not entirely certain why it&#8217;s necessary to multiply the timestamps by 1000 to get to the correct time, but it works fine&#8230;</p>
<p>And there you are. Hopefully anyone needing an economical, nice-looking timeline with dynamically-generated data can take advantage of this. But certainly, if you can work with static (or infrequently-updated) data, you may be able to use Timeline-Setter out of the box via a cron job or rake task &#8212; you could generate the CSV file for its command-line interface, run it, then copy the resulting files into your application. If you need dynamic timelines, though, I hope this post is helpful.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/masonoise.wordpress.com/184/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/masonoise.wordpress.com/184/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=184&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://masonoise.wordpress.com/2012/05/30/showing-timelines-using-timeline-setter-and-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<georss:point>37.774929 -122.419415</georss:point>
		<geo:lat>37.774929</geo:lat>
		<geo:long>-122.419415</geo:long>
		<media:content url="http://2.gravatar.com/avatar/b6ce020fad75a4b999dbf4f2ae78a6f1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">masonoise</media:title>
		</media:content>
	</item>
		<item>
		<title>Accessing Salesforce data from Ruby/Rails</title>
		<link>http://masonoise.wordpress.com/2012/03/28/accessing-salesforce-data-from-rubyrails/</link>
		<comments>http://masonoise.wordpress.com/2012/03/28/accessing-salesforce-data-from-rubyrails/#comments</comments>
		<pubDate>Wed, 28 Mar 2012 15:59:26 +0000</pubDate>
		<dc:creator>masonoise</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[salesforce]]></category>

		<guid isPermaLink="false">http://masonoise.wordpress.com/?p=173</guid>
		<description><![CDATA[I&#8217;ve done some work integrating Rails apps with Salesforce over the past few years, and have been very happy to see the new databasedotcom gem take the place of the community&#8217;s older activesalesforce gem. Thanks to work from Heroku and Pivotal Labs, it&#8217;s now very easy to push and pull data between a Rails app &#8230;<p><a href="http://masonoise.wordpress.com/2012/03/28/accessing-salesforce-data-from-rubyrails/" class="more-link">Read More</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=173&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve done some work integrating Rails apps with Salesforce over the past few years, and have been very happy to see the new <a title="databasedotcom gem" href="https://github.com/heroku/databasedotcom">databasedotcom</a> gem take the place of the community&#8217;s older activesalesforce gem. Thanks to work from Heroku and Pivotal Labs, it&#8217;s now very easy to push and pull data between a Rails app and your Salesforce organization.</p>
<p>I wrote up an article about using the gem, which is now available on the DeveloperForce site. You can go and check it out at <a title="http://wiki.developerforce.com/page/Accessing_Salesforce_Data_From_Ruby" href="http://wiki.developerforce.com/page/Accessing_Salesforce_Data_From_Ruby">http://wiki.developerforce.com/page/Accessing_Salesforce_Data_From_Ruby</a>. I hope it helps get your started if you&#8217;re finding a need to do this sort of work. So many companies rely on Salesforce now for at least their sales pipeline that it can be extremely useful to do things like extract data to show in an internal Rails dashboard, or do more complex reporting. In our case we&#8217;re also sourcing data from external places and pushing it into our Salesforce organization so that our sales/support folks can have easy access to it within their Salesforce world.</p>
<p> </p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/masonoise.wordpress.com/173/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/masonoise.wordpress.com/173/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=173&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://masonoise.wordpress.com/2012/03/28/accessing-salesforce-data-from-rubyrails/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<georss:point>37.774929 -122.419415</georss:point>
		<geo:lat>37.774929</geo:lat>
		<geo:long>-122.419415</geo:long>
		<media:content url="http://2.gravatar.com/avatar/b6ce020fad75a4b999dbf4f2ae78a6f1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">masonoise</media:title>
		</media:content>
	</item>
		<item>
		<title>Profiling Ruby using perftools.rb</title>
		<link>http://masonoise.wordpress.com/2012/03/18/profiling-ruby-using-perftools-rb/</link>
		<comments>http://masonoise.wordpress.com/2012/03/18/profiling-ruby-using-perftools-rb/#comments</comments>
		<pubDate>Sun, 18 Mar 2012 20:01:33 +0000</pubDate>
		<dc:creator>masonoise</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://masonoise.wordpress.com/?p=170</guid>
		<description><![CDATA[Having the need to profile a rake task in order to figure out why it was taking so long, I decided to take the opportunity to check out the perftools.rb gem. It proved to be interesting, though I&#8217;m still working out the best way to get useful information from it. Getting it running on my &#8230;<p><a href="http://masonoise.wordpress.com/2012/03/18/profiling-ruby-using-perftools-rb/" class="more-link">Read More</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=170&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>
Having the need to profile a rake task in order to figure out why it was taking so long, I decided to take the opportunity to check out the perftools.rb gem. It proved to be interesting, though I&#8217;m still working out the best way to get useful information from it. Getting it running on my MacBook Air running Lion (OS X 10.7) was a little involved so I thought I&#8217;d write up a post here both for my own memory as well as to help anyone else who might be interested. And it&#8217;s been a while since my last post because things have been so busy at work. Time to get back to writing things here.
</p>
<p>
The perftools.rb gem is of course on GitHub: <a href="https://github.com/tmm1/perftools.rb">here</a>. Because I needed to profile a rake task rather than part of our Rails app, I couldn&#8217;t use the rack-perftools_profiler, so I had to do it a bit more manually. First thing of course was to add the gem to the Gemfile:
</p>
<pre class="brush: ruby; title: ; notranslate">
    gem &quot;perftools.rb&quot;, &quot;~&gt; 2.0.0&quot;
</pre>
<p>
After a bundle install, I was good to go there. Next I had to put the profiling around the block of code I wanted to investigate:
</p>
<pre class="brush: ruby; title: ; notranslate">
    require 'perftools'	# At the top of the class

    PerfTools::CpuProfiler.start(&quot;/tmp/my_method_profile&quot;)
    my_method_call()
    PerfTools::CpuProfiler.stop
</pre>
<p>
It&#8217;s pretty easy. I ran my code, and then I had the file /tmp/my_method_profile. But what to do with this binary file? Well, the simplest option is to run pprof.rb on it:
</p>
<pre class="brush: ruby; title: ; notranslate">
pprof.rb --text /tmp/my_method_profile
</pre>
<p>
That will output a bunch of information, basically a list of the &#8220;samples&#8221; the profiler took in descending order of percentage of samples in the function &#8212; that is, the first entry is the one which was &#8220;seen&#8221; the most by the profiler. I recommend taking a look at the pprof documentation <a href="http://gperftools.googlecode.com/svn/trunk/doc/cpuprofile.html#pprof">here</a>.
</p>
<p>
That textual information is surely useful, but I hoped for more. Using callgrind output seemed very interesting, but I couldn&#8217;t use kcachegrind on my Mac. Thanks to <a href="https://gist.github.com/1029580">this gist</a> I was able to get qcachegrind, a Qt version, running. It&#8217;s not quite 100% happy with OS X 10.7 but it works. You&#8217;ll need Xcode installed, then follow the directions in that gist. I installed the latest &#8220;libs only&#8221; version of Qt, 4.8.0. Installing Graphviz was straightforward; you can follow the instructions in the gist or use Homebrew as well. I was then able to do the svn checkout of qcachegrind and build it. Note that the patch gist mentioned to let it open any file is no longer necessary &#8212; since that was written, a change to qcachegrind was made to allow it to open any file. Go ahead and do the qmake and make, and you should be good to go.
</p>
<p>
Okay, so now I could process the profile into callgrind format, and view it:
</p>
<pre class="brush: ruby; title: ; notranslate">
pprof.rb --callgrind /tmp/my_method_profile &gt; /tmp/my_method_profile.grind
open qcachegrind.app
</pre>
<p>
Using qcachegrind I opened the /tmp/my_method_profile.grind file, and there it was! I could view the call graphs, and get some nice views of what was going on in the code.
</p>
<p>
If all you want is a straight-forward call graph, though, you can also (once you have Graphviz installed) generate a call graph GIF image with &#8220;pprof.rb &#8211;gif /tmp/my_method_profile &gt; /tmp/my_method_profile.gif&#8221;. Open that GIF and you&#8217;ll have a very useful view of what was happening in the block of code you&#8217;re profiling.
</p>
<p>
I hope this quick summary is helpful &#8212; it&#8217;s not always easy to figure out precisely what&#8217;s happening your code, and perftools.rb can help out a great deal.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/masonoise.wordpress.com/170/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/masonoise.wordpress.com/170/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=170&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://masonoise.wordpress.com/2012/03/18/profiling-ruby-using-perftools-rb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<georss:point>37.774929 -122.419415</georss:point>
		<geo:lat>37.774929</geo:lat>
		<geo:long>-122.419415</geo:long>
		<media:content url="http://2.gravatar.com/avatar/b6ce020fad75a4b999dbf4f2ae78a6f1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">masonoise</media:title>
		</media:content>
	</item>
		<item>
		<title>Book review: PHP and MongoDB Web Development</title>
		<link>http://masonoise.wordpress.com/2012/01/24/book-review-php-and-mongodb-web-development/</link>
		<comments>http://masonoise.wordpress.com/2012/01/24/book-review-php-and-mongodb-web-development/#comments</comments>
		<pubDate>Tue, 24 Jan 2012 05:34:14 +0000</pubDate>
		<dc:creator>masonoise</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[books]]></category>
		<category><![CDATA[mongodb]]></category>

		<guid isPermaLink="false">http://masonoise.wordpress.com/?p=162</guid>
		<description><![CDATA[I recently was provided with an eBook review copy of PHP and MongoDB Web Development from Packt Publishing, by Rubayeet Islam. Being interested in MongoDB, though a bit out of date with my PHP development, I read through the book fairly quickly. As the title indicates, the author focuses on using MongoDB to provide the &#8230;<p><a href="http://masonoise.wordpress.com/2012/01/24/book-review-php-and-mongodb-web-development/" class="more-link">Read More</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=162&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>
I recently was provided with an eBook review copy of <a href="http://www.packtpub.com/php-and-mongodb-web-development-beginners-guide/book">PHP and MongoDB Web Development</a> from Packt Publishing, by Rubayeet Islam. Being interested in MongoDB, though a bit out of date with my PHP development, I read through the book fairly quickly.
</p>
<p>
As the title indicates, the author focuses on using MongoDB to provide the storage back-end for PHP web applications. After a short introduction to the basic concepts behind MongoDB, we get a walk-through of installing MongoDB and getting PHP to talk with it, before starting in on building a blog. It&#8217;s a safe example, since a blog is a reasonable candidate for a document store like MongoDB. It also provides a way to address one of the big design questions when using MongoDB, which is when to use embedded documents and when to store references. To my mind the question is glossed over a bit too quickly, but it is discussed.
</p>
<p>
Additional projects like session management and geolocation get a bit off-track, as a lot of time is spent describing the concepts rather than MongoDB, but the meatier sections that get into topics like Map-Reduce (creating a tag cloud) and web analytics are certainly worthwhile. I did feel that the chapter reviewing two MongoDB management tools could have been skipped, since the information will likely be out of date within a couple of months.
</p>
<p>
Overall, this is a reasonable beginner&#8217;s guide, as its subtitle indicates. There&#8217;s a great deal of PHP code filling its pages, which will give you a starting point if you need a boost to get going. Reading through it will give you the basics about MongoDB, and a bit more &#8212; hints on indexing, optimizing, and Map-Reduce will keep you running. A lot of the information felt cursory, and I would have appreciated more depth, but that&#8217;s probably just me wanting more than a beginner&#8217;s introduction. Perhaps more relevant were my concerns about the copy-editing and grammar. I didn&#8217;t notice any actual errors, but the grammar is quite rough and it made me wonder. It may make me old-fashioned these days, but I still expect my books to be well-edited and grammatically correct. The issue didn&#8217;t get directly in the way of the information to be had, but it&#8217;s still a pity. Nonetheless, if you&#8217;re a PHP developer and you&#8217;re looking to get started with MongoDB, you&#8217;ll doubtless find this a useful book.
</p>
<p>
<a href="http://www.packtpub.com/php-and-mongodb-web-development-beginners-guide/book">PHP and MongoDB Web Development from Packt Publishing</a>, also available from <a href="http://amzn.com/1849513627">Amazon</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/masonoise.wordpress.com/162/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/masonoise.wordpress.com/162/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=162&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://masonoise.wordpress.com/2012/01/24/book-review-php-and-mongodb-web-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<georss:point>37.774929 -122.419415</georss:point>
		<geo:lat>37.774929</geo:lat>
		<geo:long>-122.419415</geo:long>
		<media:content url="http://2.gravatar.com/avatar/b6ce020fad75a4b999dbf4f2ae78a6f1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">masonoise</media:title>
		</media:content>
	</item>
		<item>
		<title>Little Redis Book</title>
		<link>http://masonoise.wordpress.com/2012/01/23/little-redis-book/</link>
		<comments>http://masonoise.wordpress.com/2012/01/23/little-redis-book/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 18:53:56 +0000</pubDate>
		<dc:creator>masonoise</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[redis]]></category>

		<guid isPermaLink="false">http://masonoise.wordpress.com/?p=164</guid>
		<description><![CDATA[Just a quick note that Karl Seguin has created a nice mini-Redis book, available for free download. Check his announcement here and grab the book. He&#8217;s also posted the source of the book to GitHub.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=164&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Just a quick note that Karl Seguin has created a nice mini-Redis book, available for free download. Check his announcement <a href="http://openmymind.net/2012/1/23/The-Little-Redis-Book/">here</a> and grab the book. He&#8217;s also posted the source of the book to GitHub.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/masonoise.wordpress.com/164/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/masonoise.wordpress.com/164/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=164&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://masonoise.wordpress.com/2012/01/23/little-redis-book/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<georss:point>37.774929 -122.419415</georss:point>
		<geo:lat>37.774929</geo:lat>
		<geo:long>-122.419415</geo:long>
		<media:content url="http://2.gravatar.com/avatar/b6ce020fad75a4b999dbf4f2ae78a6f1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">masonoise</media:title>
		</media:content>
	</item>
		<item>
		<title>Devise and OmniAuth for Single Sign On</title>
		<link>http://masonoise.wordpress.com/2010/12/31/devise-and-omniauth-for-single-sign-on/</link>
		<comments>http://masonoise.wordpress.com/2010/12/31/devise-and-omniauth-for-single-sign-on/#comments</comments>
		<pubDate>Fri, 31 Dec 2010 22:58:53 +0000</pubDate>
		<dc:creator>masonoise</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[devise]]></category>
		<category><![CDATA[oauth]]></category>
		<category><![CDATA[omniauth]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://masonoise.wordpress.com/?p=154</guid>
		<description><![CDATA[I just wanted to put a quick link to a great blog post about using Devise and OmniAuth to create a single-sign on mechanism where multiple apps can share an authentication mechanism. It&#8217;s very straightforward; check it out here.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=154&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>
I just wanted to put a quick link to a great blog post about using Devise and OmniAuth to create a single-sign on mechanism where multiple apps can share an authentication mechanism. It&#8217;s very straightforward; check it out <a href="http://blog.joshsoftware.com/2010/12/16/multiple-applications-with-devise-omniauth-and-single-sign-on/">here</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/masonoise.wordpress.com/154/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/masonoise.wordpress.com/154/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=masonoise.wordpress.com&#038;blog=10992272&#038;post=154&#038;subd=masonoise&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://masonoise.wordpress.com/2010/12/31/devise-and-omniauth-for-single-sign-on/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<georss:point>37.774929 -122.419415</georss:point>
		<geo:lat>37.774929</geo:lat>
		<geo:long>-122.419415</geo:long>
		<media:content url="http://2.gravatar.com/avatar/b6ce020fad75a4b999dbf4f2ae78a6f1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">masonoise</media:title>
		</media:content>
	</item>
	</channel>
</rss>
