<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Technology Musings</title>
    <link>http://www.bartlettpublishing.com/site/bartpub/blog/3</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>My Beef with Model Validators in Rails</title>
      <description>&lt;p&gt;When I first started using Rails, it was a dream come true. &amp;nbsp;I estimate that I reduced the amount of code I was writing by 60-75%. &amp;nbsp;This is probably still true. &amp;nbsp;However, as I've gotten to know the platform better, there are some philosophical issues that I have with Rails. &amp;nbsp;Sometimes it is more the Rails community and its conventions rather than rails itself, but nonetheless, it continually manifests itself.&lt;/p&gt;
&lt;p&gt;My current beef - validators! &amp;nbsp;Having written lots and lots of code that interacts with lots and lots of systems, I have to say that you should never, ever, ever put in model validators. &amp;nbsp;Ever. &amp;nbsp;Validation is a process issue, not a data one. &amp;nbsp;In theory it should be a data issue, but it never ever works out that way.&lt;/p&gt;
&lt;p&gt;Here's what happens. &amp;nbsp;Let's say I have a telephone number validator for a model. &amp;nbsp;It makes sure the numbers are in the format (918) 245-2234. &amp;nbsp;If not, it gives a nice error message. &amp;nbsp;However, now let's connect that same model to an external system. &amp;nbsp;Let's now say that the author of the external system was not as picky about phone number formats. &amp;nbsp;What happens now? &amp;nbsp;Well, every record that gets migrated from that system that isn't formatted according to your desires will now get kicked out! &amp;nbsp;And it might not even show up during testing! &amp;nbsp;In addition, your pretty error messages mean practically nothing on system-&amp;gt;system communication. &amp;nbsp;So, what you have is the system randomly breaking down.&lt;/p&gt;
&lt;p&gt;This causes even more problems in long-term maintenance. &amp;nbsp;I've had many bugs pop up because someone added a validator that broke several processes. &amp;nbsp;It worked in all of their tests, but they weren't thinking about all of the ways the system was used. &amp;nbsp;For instance, we decided to lock down the characters used in our usernames a little more. &amp;nbsp;The programmer decided to implement it as a validator. &amp;nbsp;Well, the problem is that several users already had usernames that didn't match the validator. &amp;nbsp;So what happened? &amp;nbsp;Those records just stopped saving. &amp;nbsp;Not just when there was someone who was at the terminal, where they could see the error message, but every job started erroring out because of users who had faulty names.&lt;/p&gt;
&lt;p&gt;Because of these issues, I *always* do validation in my controller, and *never* in the model. &amp;nbsp;It is true that there are probably workarounds for all of these issues, but the point is that they are *not* that exceptional! &amp;nbsp;They are everywhere! &amp;nbsp;What would be nice is to have validators which could be run optionally, in specific situations. &amp;nbsp;So, a controller could declare that it was using :data_entry validations, and then the model would only run those validators. &amp;nbsp;So, it would look something like this:&lt;/p&gt;
&lt;p&gt;In the model:&lt;/p&gt;
&lt;pre&gt;validates_presence_of :email, :for =&amp;gt; [:data_entry]&lt;/pre&gt;
&lt;p&gt;In the controller:&lt;/p&gt;
&lt;pre&gt;uses_validators :data_entry&lt;/pre&gt;
&lt;p&gt;One of the issues I have found with dynamic languages such as ruby is that errors arise when &quot;magic&quot; is sprinkled in unexpected places. &amp;nbsp;Ruby magic is awesome, but when I do something simple and it won't save, it is sometimes hard to even locate where the error is. &amp;nbsp;Explicitly declaring which validator set you are using allows programmers to more easily see what they are doing, and only apply magic code where it goes.&lt;/p&gt;
&lt;p&gt;Someday I'll write a package like this --- when I get extra time :)&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Thu, 09 May 2013 15:06:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/369</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/369</guid>
    </item>
    <item>
      <title></title>
      <description>&lt;p&gt;Why the tabs-vs-spaces debate matters:&lt;/p&gt;
&lt;p&gt;
&lt;pre style=&quot;background-color: #eeeeee; padding: 10px; font-size: 11px; white-space: pre-wrap; color: #333333; line-height: 18px;&quot;&gt;&lt;code&gt;Inconsistent indentation: 2 spaces were used for indentation, but the rest of the document was indented using 1 tab.
&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;Everyone - indent with tabs. &amp;nbsp;Then you can control the indentation using your editor's settings. &amp;nbsp;DO NOT indent with spaces. &amp;nbsp;And DO NOT use any programming language or configuration system that cares about indentation.&lt;/div&gt;
&lt;/p&gt;</description>
      <author></author>
      <pubDate>Tue, 07 May 2013 20:02:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/368</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/368</guid>
    </item>
    <item>
      <title>A Review of Several Nerf and Nerf-Like Guns</title>
      <description>&lt;p&gt;Usually I don't splurge on things like Nurf guns, but our family was challenged to a dual, and I decided we needed to load up. &amp;nbsp;The kids had been saving money, so they all got to purchase their own gun, and so my only purchase was for my own. &amp;nbsp;Anyway, I thought I'd post what everyone bought and a short review of each of them. &amp;nbsp;Here's what we bought:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.buzzbeetoys.com/USglobal/AirWarriors/69500.html&quot;&gt;Buzz Bee RADS 12&lt;/a&gt; (&lt;a href=&quot;http://www.amazon.com/gp/product/B0050M52V0/ref=as_li_ss_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=B0050M52V0&amp;amp;linkCode=as2&amp;amp;tag=bartlepublis-20&quot; target=&quot;_blank&quot;&gt;amazon&lt;/a&gt;) (top left)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.buzzbeetoys.com/USglobal/AirWarriors/50700.html&quot;&gt;Buzz Bee Double-Barrel Shotgun&lt;/a&gt; (&lt;a href=&quot;http://www.amazon.com/gp/product/B005LORAZS/ref=as_li_ss_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=B005LORAZS&amp;amp;linkCode=as2&amp;amp;tag=bartlepublis-20&quot; target=&quot;_blank&quot;&gt;amazon&lt;/a&gt;) (middle)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.hasbro.com/nerf/en_US/shop/details.cfm?R=BCC00BF4-5056-900B-10B0-938A6FFDF1E8:en_US&quot;&gt;Nerf Vortex Proton&lt;/a&gt; (&lt;a href=&quot;http://www.amazon.com/gp/product/B004SKQNDQ/ref=as_li_ss_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=B004SKQNDQ&amp;amp;linkCode=as2&amp;amp;tag=bartlepublis-20&quot;&gt;here is a similar gun on amazon&lt;/a&gt;) (top right)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.buzzbeetoys.com/USglobal/AirWarriors/61500.html&quot;&gt;Buzz Bee Tek-3&lt;/a&gt;&amp;nbsp;(3-pack) (&lt;a href=&quot;http://www.amazon.com/gp/product/B004286GKO/ref=as_li_ss_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=B004286GKO&amp;amp;linkCode=as2&amp;amp;tag=bartlepublis-20&quot;&gt;amazon&lt;/a&gt;) (bottom middle left)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.hasbro.com/nerf/en_US/shop/details.cfm?R=C7550C58-5056-900B-100A-3E6EB148C8A8:en_US&quot; target=&quot;_blank&quot;&gt;Nerf N-Strike Elite Retaliator&lt;/a&gt; (&lt;a href=&quot;http://www.amazon.com/gp/product/B0083TXWXC/ref=as_li_ss_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=B0083TXWXC&amp;amp;linkCode=as2&amp;amp;tag=bartlepublis-20&quot; target=&quot;_blank&quot;&gt;amazon&lt;/a&gt;) (bottom)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;Below is a picture of all of the guns:&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;&lt;img src=&quot;/site/bartpub/download/22?disposition=inline&quot; alt=&quot;&quot; width=&quot;400&quot; /&gt;&lt;/div&gt;
&lt;p&gt;We bought these at Target, and none of them cost more than $25. &amp;nbsp;In fact, most of them were $10 or less.&lt;/p&gt;
&lt;p&gt;The gun with the most &quot;cool factor&quot; was the Nerf Retaliator. &amp;nbsp;This gun is modular and therefore can actually be transformed into four different styles below:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/site/bartpub/download/23?disposition=inline&quot; alt=&quot;&quot; width=&quot;400&quot; /&gt;&lt;/p&gt;
&lt;p&gt;If you remove the stock and the barrel, you get a very nice basic gun similar to a &lt;a href=&quot;http://en.wikipedia.org/wiki/%C5%A0korpion_vz._61&quot; target=&quot;_blank&quot;&gt;Skorpion&lt;/a&gt; (bottom right). &amp;nbsp;If you have a stock without a barrel, you get a gun very reminiscent of a &lt;a href=&quot;http://en.wikipedia.org/wiki/Heckler_%26_Koch_UMP&quot; target=&quot;_blank&quot;&gt;UMP45&lt;/a&gt;. &amp;nbsp;If you have a barrel but no stock, it looks a bit like an &lt;a href=&quot;http://en.wikipedia.org/wiki/Heckler_%26_Koch_MP5&quot; target=&quot;_blank&quot;&gt;MP5&lt;/a&gt;. &amp;nbsp;With all of the attachments, it could be really any assault rifle, but it most reminds me of an &lt;a href=&quot;http://en.wikipedia.org/wiki/M4_carbine&quot; target=&quot;_blank&quot;&gt;M4&lt;/a&gt;&amp;nbsp;or &lt;a href=&quot;http://en.wikipedia.org/wiki/FN_FAL&quot; target=&quot;_blank&quot;&gt;FAL&lt;/a&gt;. &amp;nbsp;Now, I should point out, this is pretty much all for show - I didn't detect any advantage of having a barrel attached - but it looks pretty intimidating nonetheless. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;The Retaliator fires well, and with a long range , but is *very* erratic. &amp;nbsp;In our battle with our friends, I'm not sure I hit *anyone* with this gun. &amp;nbsp;It is mega-cool, and shoots pretty far, but don't count on actually hitting anything.&lt;/p&gt;
&lt;p&gt;The gun that actually shot the best was the Vortex Proton - and I think it only cost $9. &amp;nbsp;The Proton is one of Nerf's new disc-firing guns. &amp;nbsp;The disks are Nerf disks so they don't hurt. &amp;nbsp;However, the disks are *very* aerodynamic, so they actually fly straight! &amp;nbsp;The Vortex is a single shot, and it takes a little bit to load, but nonetheless I had the best success with it because it was so accurate! &amp;nbsp;I could be sure to know that the disk would fly exactly to where I aimed it! &amp;nbsp;The only drawback, as I said, was that it was a single-shot, and didn't even have a spot to hold additional ammo. &amp;nbsp;So, reloading was problematic because it took time, and fumbling around with ammo was difficult. &amp;nbsp;I think if you got a multi-shot version of this you would have an amazing gun! &amp;nbsp;&lt;/p&gt;
&lt;p&gt;Another good gun is the Buzz Bee RADS 12. &amp;nbsp;This is a twelve-shot gun that you pull back on a lever to cock it. &amp;nbsp;It shoots decently and doesn't cost very much. &amp;nbsp;Overall I would say that it is a decent purchase, but my 5-year-old was the one to purchase it, and it took too much hand strength to cock the gun. &amp;nbsp;He could do it, but only if he held it on the ground with one hand and pulled with the other - not very helpful in a gun battle.&lt;/p&gt;
&lt;p&gt;The worst gun was the Buzz Bee double-barrel shotgun. &amp;nbsp;This was not worth buying. &amp;nbsp;Here are the problems with the gun:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It takes a *lot* of effor to load the gun. &amp;nbsp;You have to pull it apart really hard, and it is not always clear when it is fully cocked (pulling it apart is what cocks it)&lt;/li&gt;
&lt;li&gt;The bullets have to be loaded into &quot;shells&quot; (to make it more realistic). &amp;nbsp;This is just a hassle. &amp;nbsp;My son likes this, but it is unhelpful.&lt;/li&gt;
&lt;li&gt;The shells eject when you pull apart the gun. &amp;nbsp;Again, this aims for realism, but doesn't help during a battle, and is just more pieces to get lost. &amp;nbsp;In fact, in this case, they actually seem to be actively trying to get lost.&lt;/li&gt;
&lt;li&gt;It only holds two shots. &amp;nbsp;This seems pretty obvious for a double-barrel shotgun, but the fact that it takes so long to load makes this really problematic.&lt;/li&gt;
&lt;li&gt;It doesn't shoot very far. &amp;nbsp;It's moderately accurate, but, really, it has an effective range of about 6-12 feet.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Anyway, my 6-year-old likes it because of the &quot;realism&quot;, but I think that if we do too many more battles, he will realize the problems with the gun.&lt;/p&gt;
&lt;p&gt;The next gun is the Buzz Bee Tek-3. &amp;nbsp;This is a tiny gun with three shots. &amp;nbsp;However, it does not auto-rotate the barrel. &amp;nbsp;Between shots, you must BOTH cock the gun AND rotate the barrel. &amp;nbsp;However, for a tiny gun, it packs a decent punch and is relatively easy to use. &amp;nbsp;At Target, they had a 3-pack for $6. &amp;nbsp;That's right, 3 guns for $6. &amp;nbsp;It makes a good backup weapon (like a boot gun).&lt;/p&gt;
&lt;p&gt;Also in the picture is an older Nerf gun that we already had - I believe it is a &lt;a href=&quot;http://nerf.wikia.com/wiki/Strikefire&quot; target=&quot;_blank&quot;&gt;Nerf Dart Tag Strikefire&lt;/a&gt;. &amp;nbsp;This is an old gun, but still shoots decently. &amp;nbsp;It is a single-shot, muzzle-loaded pistol, but also has holding spots for five additional rounds. &amp;nbsp;This original came with Nerf Dart Tag darts, but I think it can fire most anything. &amp;nbsp;It works really well as a simple, basic gun.&lt;/p&gt;
&lt;p&gt;Anyway, if you are looking for Nurf or Nurf-like guns, I hope this review was helpful to you!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Sun, 07 Oct 2012 02:23:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/362</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/362</guid>
    </item>
    <item>
      <title>Rails, CoffeeScript, and Java</title>
      <description>&lt;p&gt;I *hate* the direction that Rails is moving. &amp;nbsp;It is becoming a bloated piece of garbage. &amp;nbsp;I got into Rails precisely because Rails got out of my way most of the time, but was easy to use right where I needed it. &amp;nbsp;ActiveRecord was a thin shell over SQL. &amp;nbsp;Therefore, if there was a problem, I could easily diagnose it, because I knew SQL. &amp;nbsp;It added a few bits of magic, but those were usually pretty understandable. &amp;nbsp;Likewise with the javascript helpers and the like. &amp;nbsp;If you needed something done, just pop into Javascript and patch it up.&lt;/p&gt;
&lt;p&gt;This contrasted heavily with J2EE. &amp;nbsp;I used J2EE for a while, but it turns out that if you want to use J2EE you have to commit to it like it's a religion. &amp;nbsp;If you don't know 20 different platform libraries, you can't even do a hello world in J2EE. &amp;nbsp;When you finally get it working, you don't know what the heck is even going on. &amp;nbsp;Some magic is happening somewhere, but it is beyond what is plainly visible. &amp;nbsp;This, and the fact that Ruby is very metaprogramming-ish, was the reason I chose Rails.&lt;/p&gt;
&lt;p&gt;However, starting with Rails 3, the Rails team decided that it was simply going to do everything for you, and everything was going to be done in domain-specific languages. &amp;nbsp;Thus, instead of the required list of languages/platforms being Ruby/Rails/SQL/Javascript, it has balooned out to Ruby/Rails/SQL/Javascript/Coffeescript/SASS/ECO/Node.js, and probably a few others I'm forgetting. &amp;nbsp;The asset pipeline is kind of cool, but it's yet another place for things to go wrong. &amp;nbsp;I think the anti-CSS measure of auto-h()ing code is terrible. &amp;nbsp;If you wanted to go that way, instead you should use Perl's taint feature, and just give errors if you display tainted values. &amp;nbsp;The idea that random code should transform my strings is horrible.&lt;/p&gt;
&lt;p&gt;Finally, I understand the reason for getting rid of the javascripty stuff from rails core, but some of those were really what made the platform really rock. &amp;nbsp;I think they have missed the mark - they put the ease-of-use in the wrong places, and instead have made sure that no one that doesn't have a relgious commitment to the software stack will ever find it usable. &amp;nbsp;It has basically gone the way of J2EE, and I am now looking for a new platform to love.&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Mon, 01 Oct 2012 20:32:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/361</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/361</guid>
    </item>
    <item>
      <title>Today's Thoughts on Algorithmic Information Theory</title>
      <description>&lt;p&gt;I know this won't make a lot of sense to most people, but I thought I needed to store these thoughts in a more permanent place before I forget them.&amp;nbsp; I've been reading a paper today on Algorithmic Information Theory, and it make me think these thoughts (most of which are probably ill-founded):&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Is the Chaitin halting probability really a probability?&amp;nbsp; In other words, if I have the first 5 bits of omega, does this mean that a random sampling of all programs will really match this value to some extent?&lt;/li&gt;
&lt;li&gt;To what extent is self-delimiting programs an intrinsic part of AIT, vs just a cheap trick to get the math right?&amp;nbsp; It makes sense simply because you need the program length.&amp;nbsp; But on the other hand, if omega is a probability, it seems like having the program length pre-coded would do a number on its interpretation as a probability.&lt;/li&gt;
&lt;li&gt;If log2(2^w) is w, is perhaps log2(w) = c?&amp;nbsp; Is c the complexity number I'm looking for for my axioms?&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Is it possible to express the idea of a formal relationship to be the relationship between the algorithmic specification and its logical depth?&amp;nbsp; I.e. we should expect a material cause when logical depth is low, but a formal one when logical depth is high?&amp;nbsp; Could this be expressed as a ratio?&lt;/li&gt;
&lt;li&gt;Algorithmic complexity on partial specifications.&amp;nbsp; The word &quot;red&quot;, as implemented in 12 pt font or written in the clouds.&amp;nbsp; Perhaps the partial specification is something that can be detected non-algorithmically, via an Oracle machine?&amp;nbsp; In other words, instead of &quot;give me the Xth object that matches specification X, you say, give me *an* object that matches specification X.&amp;nbsp; It does not require an iteration over the whole of infinity, but a potentially large part of it very quickly.&amp;nbsp; Or, perhaps, it drops it a level of Cantorian infinity.&lt;/li&gt;
&lt;li&gt;Recognizers vs generators = P/NP problem = logical depth vs algorithmic complexity&lt;/li&gt;
&lt;li&gt;What is the relationship between the constant given in AIT vs expressibility of language?&amp;nbsp; In other words, if C is small, then it is easier to express random strings, at the penalty of having no easily expressible strings.&amp;nbsp; A larger C will permit more compressibility.&amp;nbsp; This might also be usable, at least in theory, to determine the total number of &quot;special&quot; strings available.&lt;/li&gt;
&lt;li&gt;How can algorithmic information theory be expanded for programs that take arguments? (note - number of arguments shouldn't matter, only whether one of them is itself a program, perhaps? or if the result is a program?&amp;nbsp; Maybe what the Wolfram class of the argument is?)&lt;/li&gt;
&lt;li&gt;Might semantics and apobetics be higher Turing degrees?&lt;/li&gt;
&lt;li&gt;Might ethical norms be an expression of compressibility across Turing degrees?&lt;/li&gt;
&lt;li&gt;What about bad plans?&amp;nbsp; Is it possible to state, even in abstract, non-determinable terms, what a bad plan is?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Sun, 23 Sep 2012 04:55:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/359</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/359</guid>
    </item>
    <item>
      <title>Autoreleased with No Pool in Place</title>
      <description>&lt;p&gt;Before Apple's ARC, you would often have to manage memory semi-manually.&amp;nbsp; Before operation queues, you would also have to manage setting up autorelease pools on new threads.&amp;nbsp; If you didn't, you would get an error such as:&lt;/p&gt;
&lt;pre&gt;autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug&lt;/pre&gt;
&lt;p&gt;However, the other day, I started getting these myself!&amp;nbsp; I was a little shocked - what on earth was I doing that required an autorelease pool?&amp;nbsp; Well, eventually I figured it out.&amp;nbsp; It turns out that if you have custom +load() functions on your classes (these get called whenever the classes load - I use them for registering handlers and such), this is another situation in which you have to set up your own autorelease pool if you do any object creation.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So, in your +load() function (or, depending on what you are doing, in functions that +load calls), just wrap it with&lt;/p&gt;
&lt;pre&gt;@autoreleasepool {&lt;br /&gt;     Your Code Here&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;And it works!&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Wed, 15 Aug 2012 18:54:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/358</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/358</guid>
    </item>
    <item>
      <title>Simple Sage Plots for Teaching Functions</title>
      <description>&lt;p&gt;I'm teaching calculus to some homeschool students this year, and I wanted to have a bunch of function plots printed out to show them.&amp;nbsp; Therefore, I turned to Sage, which I have never used.&amp;nbsp; It is great!&amp;nbsp; You have to know a few other math software pieces to really understand it, but it's not that bad.&amp;nbsp; Someone needs to do a general &quot;how to use sage&quot;, and some day I might.&lt;/p&gt;
&lt;p&gt;Anyway, here's my quick function for plotting graphs for students that some of you might like.&lt;/p&gt;
&lt;p&gt;In one of the evaluation boxes, type the following:&lt;/p&gt;
&lt;pre&gt;def simpleplot(f, range=(-5,5,-5,5)):&lt;br /&gt;  p = plot(f, (x, range[0], range[1]))&lt;br /&gt;  p += text(&quot;$&quot; + latex(f) + &quot;$&quot;, (0, range[2] - (range[3] - range[2]) * 0.1), fontsize=30, rgbcolor=(1,0,0))&lt;br /&gt;  p.axes_range(range[0], range[1], range[2], range[3])&lt;br /&gt;  show(p, figsize=12)&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;What this does is create a function called &quot;simpleplot&quot; which will do the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Plot the given function on a default domain of -5, 5&lt;/li&gt;
&lt;li&gt;Typeset the function using LaTeX, and insert the function slightly below the graph (I calculated it at 10% of the graph size).&amp;nbsp; It prints in red at 30 point size.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Set the axes to be -5, 5, -5, 5 (I used uniform axes on all the functions so they can compare the differences between graphs easier)&lt;/li&gt;
&lt;li&gt;Draw the whole thing at 3x the normal size (figsize=12 - default is 4).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, I can just do:&lt;/p&gt;
&lt;pre&gt;simpleplot(1/x)&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;And it gives me my output!&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Sun, 05 Aug 2012 02:09:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/357</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/357</guid>
    </item>
    <item>
      <title>DVD Rescue!  Getting files off of an unfinalized DVD</title>
      <description>&lt;p&gt;Just wanted to shout out and say thanks to Flay for saving me! &amp;nbsp;I had a DVD that I forgot to finalize, but Flay had a nice set of instructions for &lt;a href=&quot;http://flay.jellybee.co.uk/2011/01/how-to-get-files-off-unfinalized-dvd.html&quot; target=&quot;_blank&quot;&gt;how to manually copy off the files from the DVD drive&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now I can finish editing and posting the videos for the &lt;a href=&quot;http://www.blythinstitute.org/eandm2012&quot; target=&quot;_blank&quot;&gt;Engineering and Metaphysics&lt;/a&gt; conference.&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Mon, 23 Jul 2012 02:44:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/356</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/356</guid>
    </item>
    <item>
      <title>iOS Bug - insertNewObjectForEntityName: deleteObject and rollback</title>
      <description>&lt;p&gt;I've been chasing down a wierd bug where, on an NSManagedObjectContext, the hasChanges method keeps returning YES even after a rollback.&amp;nbsp; It turns out, if you do the following sequence, hasChanges will *never* be cleared:&lt;/p&gt;
&lt;pre&gt;MyClass *c = [NSEntityDescription insertNewObjectForEntityName:@&quot;MyClass&quot; inContext:ctx];&lt;br /&gt;//Do other stuff&lt;br /&gt;[ctx deleteObject:c];&lt;br /&gt;// Do other stuff&lt;br /&gt;[ctx rollback];&lt;br /&gt;[ctx hasChanges]; // Returns YES!&lt;/pre&gt;
&lt;p&gt;In my own case, I got around it by not deleting the object, and just rolling back if I wanted it gone, but that won't work for everyone.&amp;nbsp; So, I did:&lt;/p&gt;
&lt;pre&gt;MyClass *c = [NSEntityDescription insertNewObjectForEntityName:@&quot;MyClass&quot; inContext:ctx];&lt;br /&gt;//Do other stuff&lt;br /&gt;[ctx rollback]; // Don't delete! just roll back&lt;br /&gt;//Do other stuff&lt;br /&gt;[ctx rollback]; // Now it works&lt;br /&gt;[ctx hasChanges]; // Returns NO like it should&lt;br /&gt;&lt;/pre&gt;</description>
      <author>JB</author>
      <pubDate>Fri, 13 Jul 2012 16:39:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/355</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/355</guid>
    </item>
    <item>
      <title>Why I Won't Be Participating in StackOverflow.com Anymore</title>
      <description>&lt;p&gt;I have historically been grateful for stackoverflow.com, but I think that perhaps they may be getting overly full of themselves and self-conscious.&lt;/p&gt;
&lt;p&gt;I have long used their site to get answers, especially to iOS questions. &amp;nbsp;It always seems that someone answers any question I might have. &amp;nbsp;I've always wanted to give back, but found that nearly every questions someone else has already answered.&lt;/p&gt;
&lt;p&gt;So the other day I was trying to figure something out, and the answer on StackOverflow was that it was not possible. &amp;nbsp;I spent a day messing around, and actually figured out how to do it (read about it &lt;a href=&quot;/site/bartpub/blog/3/entry/350&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;). &amp;nbsp;So, having spent most of the morning trying to find if anyone had accomplished this, I actually found three different StackOverflow.com questions pertaining to it, as well as several sites on the Internet. &amp;nbsp;So what did I do? &amp;nbsp;I decided the best way to let people know about the answer was to write a blog post about it, and then point people to the blog to find the answer in each question. &amp;nbsp;This was going to be my way of giving back.&lt;/p&gt;
&lt;p&gt;So what happened? &amp;nbsp;Well, two of my comments got deleted from StackOverflow, and one had a comment from a moderator attached accusing me of self-promotion!!!! &amp;nbsp;Because I solved a problem that had been outstanding for a year, and told people the answer!!!!&lt;/p&gt;
&lt;p&gt;So, in the future, I will just post to my blog, and leave StackOverflow out of it. &amp;nbsp;You can come here for the answers. &amp;nbsp;I don't have enough brain space to deal with that kind of junk.&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Sat, 12 May 2012 03:56:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/354</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/354</guid>
    </item>
    <item>
      <title>Engineering and Metaphysics 2012 Conference</title>
      <description>&lt;p&gt;For those interested in engineering and theology and philosophy, this conference is for you! &amp;nbsp;I've got two talks slated for the conference - come and listen! &amp;nbsp;Lots of fascinating stuff from a number of disciplines:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.eandm2012.com/&quot; target=&quot;_blank&quot;&gt;www.eandm2012.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can see the abstract list &lt;a href=&quot;http://www.eandm2012.com/abstracts.php&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;&amp;nbsp;and the conference flyer &lt;a href=&quot;http://www.eandm2012.com/Flyer.pdf&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Thu, 10 May 2012 21:16:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/352</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/352</guid>
    </item>
    <item>
      <title>iOS - using storyboard relationships for custom view controller containment</title>
      <description>&lt;p&gt;One thing that iOS forgot to do with the release of storyboards and iOS 5 is support for custom &quot;relationship&quot; segues. &amp;nbsp;In addition to normal segues, UINavigationController and UITabBarController have what are called &quot;relationships&quot;, which allow you to define containment information for these controllers. &amp;nbsp;So, for the navigation controller, you define the root view controller, and for the tab bar controller, you define the list of view controllers. &amp;nbsp;This is all done in a neat interface in the storyboard editor (which is the replacement for interface builder).&lt;/p&gt;
&lt;p&gt;Another cool feature in iOS is &quot;containment&quot;, which is basically a way of letting you write view controllers which contain other view controllers. &amp;nbsp;This was not really allowed in iOS 4, but they've added some basic support for it. &amp;nbsp;Unfortunately, the way that you might want to use containment with storyboarding is through relationships, but iOS doesn't provide a way to do custom relationships in storyboards - or even their default ones on custom view controllers.&lt;/p&gt;
&lt;p&gt;My own task was to create a tab bar controller with the tabs at the *top*. &amp;nbsp;I had a few ideas on how I might approach this problem. &amp;nbsp;Subclassing UITabBarController didn't seem like a good idea. &amp;nbsp;So I tried several others.&lt;/p&gt;
&lt;p&gt;One possible way was duck typing. &amp;nbsp;I thought that perhaps I could pull a fast on on the storyboard editor. &amp;nbsp;What I would do is define my own class that mimicked UITabBarController without actually inheriting from it. &amp;nbsp;Then, I could create my relationships with the storyboard editor, and then substitute my own non-tab-bar controller at the last minute. &amp;nbsp;This failed miserably. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;Firts of all, the storyboard editor doesn't like you to substitute non-subclasses for the class that it wants. &amp;nbsp;If you try to set it to a non-subclass of UITabBarController, it won't give you an error, but it won't save the change, either.&lt;/p&gt;
&lt;p&gt;I tried to work around this by making my class inherit from UITabBarController while I was editing the storyboard, and then change it back for the compile. &amp;nbsp;This worked momentarily, but in the end, it turns out that the &quot;relationship&quot; segues aren't set via getters and setters. &amp;nbsp;I imagine there is an internal API that is being used.&lt;/p&gt;
&lt;p&gt;Therefore, I next tried overriding initWithCoder and reading the nib values myself. &amp;nbsp;Unfortunately, I was not successful at guessing the keys for decoding.&lt;/p&gt;
&lt;p&gt;Then, it hit me. &amp;nbsp;What I need to do is to mix subclassing UITabBarController with not mixing UITabBarController. &amp;nbsp;So here's what I did:&lt;/p&gt;
&lt;p&gt;class 1: MyTabBarController&lt;/p&gt;
&lt;p&gt;This is just a shell class, but it inherits from UITabBarController. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;class 2: MyTabBarControllerImplementation&lt;/p&gt;
&lt;p&gt;This is your real implementation class, and only needs to inherit from UIViewController. &amp;nbsp;Make it work like you want it to.&lt;/p&gt;
&lt;p&gt;What you are going to do is designate your tab bar controllers to be of type MyTabBarController in the storyboard editor. &amp;nbsp;Then, when viewDidLoad is called on MyTabBarController, the view controller de-registers the view controllers from itself, creates an instance of MyTabBarControllerImplementation, moves the view controllers over there, and then replaces itself with MyTabBarControllerImplementation.&lt;/p&gt;
&lt;p&gt;Anyway, here's the code. &amp;nbsp;It's really rough, but works at the moment. &amp;nbsp;I'm open to improvements:&lt;/p&gt;
&lt;p&gt;MyTabBarController.h:&lt;/p&gt;
&lt;pre&gt;&lt;span class=&quot;s1&quot;&gt;#import &lt;/span&gt;&amp;lt;UIKit/UIKit.h&amp;gt;&lt;br /&gt;&lt;span class=&quot;s2&quot;&gt;@interface&lt;/span&gt; MyTabBarController : &lt;span class=&quot;s3&quot;&gt;UITabBarController&lt;br /&gt;&lt;/span&gt;@end&lt;/pre&gt;
&lt;p&gt;MyTabBarController.m:&lt;/p&gt;
&lt;pre&gt;&lt;span class=&quot;s1&quot;&gt;#import &lt;/span&gt;&quot;MyTabBarController.h&quot;&lt;br /&gt;&lt;span class=&quot;s1&quot;&gt;#import &lt;/span&gt;&quot;MyTabBarControllerImplementation.h&quot;&lt;span class=&quot;s2&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@implementation&lt;/span&gt; JBTabController&lt;br /&gt;- (&lt;span class=&quot;s2&quot;&gt;void&lt;/span&gt;)viewDidLoad&lt;br /&gt;{&lt;br /&gt;&lt;span class=&quot;s3&quot;&gt;&amp;nbsp; &amp;nbsp; [&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt; &lt;/span&gt;viewDidLoad&lt;span class=&quot;s3&quot;&gt;];&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;JBTestContainerViewController&lt;span class=&quot;s3&quot;&gt; *vc = [[&lt;/span&gt;JBTestContainerViewController&lt;span class=&quot;s3&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;] &lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;];&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;NSArray&lt;span class=&quot;s3&quot;&gt; *vclist = &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;.&lt;/span&gt;viewControllers&lt;span class=&quot;s3&quot;&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;&amp;nbsp; &amp;nbsp; [&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt; &lt;/span&gt;setViewControllers&lt;span class=&quot;s3&quot;&gt;:[&lt;/span&gt;&lt;span class=&quot;s5&quot;&gt;NSArray&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt; &lt;/span&gt;array&lt;span class=&quot;s3&quot;&gt;] &lt;/span&gt;animated&lt;span class=&quot;s3&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;NO&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;];&lt;br /&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;vc.&lt;span class=&quot;s6&quot;&gt;viewControllers&lt;/span&gt; = vclist;&lt;br /&gt;&lt;span class=&quot;s3&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;NSMutableArray&lt;span class=&quot;s3&quot;&gt; *navlist = [&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;.&lt;/span&gt;navigationController&lt;span class=&quot;s3&quot;&gt;.&lt;/span&gt;viewControllers&lt;span class=&quot;s3&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;mutableCopy&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;];&lt;br /&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;[navlist &lt;span class=&quot;s4&quot;&gt;replaceObjectAtIndex&lt;/span&gt;:(navlist.&lt;span class=&quot;s5&quot;&gt;count&lt;/span&gt; - &lt;span class=&quot;s7&quot;&gt;1&lt;/span&gt;) &lt;span class=&quot;s4&quot;&gt;withObject&lt;/span&gt;:vc];&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;span class=&quot;s3&quot;&gt;&amp;nbsp; &amp;nbsp; [&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s5&quot;&gt;navigationController&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt; &lt;/span&gt;setViewControllers&lt;span class=&quot;s3&quot;&gt;:navlist &lt;/span&gt;animated&lt;span class=&quot;s3&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;NO&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;];&lt;br /&gt;&lt;/span&gt;}&lt;br /&gt;@end&lt;/pre&gt;
&lt;p class=&quot;p1&quot;&gt;MyTabBarControllerImplementation.h:&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;span class=&quot;s1&quot;&gt;#import &lt;/span&gt;&amp;lt;UIKit/UIKit.h&amp;gt;&lt;br /&gt;&lt;span class=&quot;s2&quot;&gt;@interface&lt;/span&gt;&amp;nbsp;MyTabBarControllerImplementation&amp;nbsp;: &lt;span class=&quot;s3&quot;&gt;UIViewController&lt;/span&gt;&amp;lt;&lt;span class=&quot;s3&quot;&gt;UITabBarDelegate&lt;/span&gt;&amp;gt;&lt;br /&gt;@property&lt;span class=&quot;s4&quot;&gt; (&lt;/span&gt;nonatomic&lt;span class=&quot;s4&quot;&gt;) &lt;/span&gt;int&lt;span class=&quot;s4&quot;&gt; selectedIndex;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@property&lt;/span&gt; (&lt;span class=&quot;s2&quot;&gt;strong&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;nonatomic&lt;/span&gt;) &lt;span class=&quot;s3&quot;&gt;NSArray&lt;/span&gt; *viewControllers;&lt;br /&gt;@property&lt;span class=&quot;s4&quot;&gt; (&lt;/span&gt;strong&lt;span class=&quot;s4&quot;&gt;, &lt;/span&gt;nonatomic&lt;span class=&quot;s4&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;UITabBar&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt; *bar;&lt;br /&gt;&lt;/span&gt;@end&lt;/pre&gt;
&lt;p class=&quot;p1&quot;&gt;MyTabBarControllerImplementation.m:&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;span class=&quot;s1&quot;&gt;#import &lt;/span&gt;&quot;MyTabBarControllerImplementation.h&quot;&lt;br /&gt;&lt;span class=&quot;s2&quot;&gt;@implementation&lt;/span&gt;&amp;nbsp;MyTabBarControllerImplementation&lt;br /&gt;&lt;span class=&quot;s2&quot;&gt;@synthesize&lt;/span&gt; viewControllers = &lt;span class=&quot;s3&quot;&gt;_viewControllers&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;s2&quot;&gt;@synthesize&lt;/span&gt; selectedIndex = &lt;span class=&quot;s3&quot;&gt;_selectedIndex&lt;/span&gt;;&lt;br /&gt;@synthesize&lt;span class=&quot;s4&quot;&gt; bar = &lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;_bar&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;;&lt;br /&gt;&lt;/span&gt;-(&lt;span class=&quot;s5&quot;&gt;CGRect&lt;/span&gt;) subviewFrame {&lt;br /&gt;&lt;span class=&quot;s4&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;CGRect&lt;span class=&quot;s4&quot;&gt; f = &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;.&lt;/span&gt;view&lt;span class=&quot;s4&quot;&gt;.&lt;/span&gt;frame&lt;span class=&quot;s4&quot;&gt;;&lt;br /&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;s2&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s6&quot;&gt;CGRectMake&lt;/span&gt;(&lt;span class=&quot;s7&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;s7&quot;&gt;30&lt;/span&gt;, f.&lt;span class=&quot;s5&quot;&gt;size&lt;/span&gt;.&lt;span class=&quot;s5&quot;&gt;width&lt;/span&gt;, f.&lt;span class=&quot;s5&quot;&gt;size&lt;/span&gt;.&lt;span class=&quot;s5&quot;&gt;height&lt;/span&gt; - &lt;span class=&quot;s7&quot;&gt;30&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;-(&lt;span class=&quot;s2&quot;&gt;void&lt;/span&gt;) reloadBarInfo {&lt;br /&gt;&lt;span class=&quot;s4&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;NSMutableArray&lt;span class=&quot;s4&quot;&gt; *itms = [&lt;/span&gt;NSMutableArray&lt;span class=&quot;s4&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s6&quot;&gt;arrayWithCapacity&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;_viewControllers&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;.&lt;/span&gt;count&lt;span class=&quot;s4&quot;&gt;];&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;(&lt;/span&gt;UIViewController&lt;span class=&quot;s4&quot;&gt; *vc &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;_viewControllers&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;) {&lt;br /&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;s5&quot;&gt;UITabBarItem&lt;/span&gt; *itm = [[&lt;span class=&quot;s5&quot;&gt;UITabBarItem&lt;/span&gt; &lt;span class=&quot;s6&quot;&gt;alloc&lt;/span&gt;] &lt;span class=&quot;s6&quot;&gt;initWithTitle&lt;/span&gt;:vc.&lt;span class=&quot;s5&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;s6&quot;&gt;image&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;s6&quot;&gt;tag&lt;/span&gt;:&lt;span class=&quot;s7&quot;&gt;0&lt;/span&gt;];&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;[itms &lt;span class=&quot;s6&quot;&gt;addObject&lt;/span&gt;:itm];&lt;br /&gt;&lt;span class=&quot;s4&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [vc &lt;/span&gt;didMoveToParentViewController&lt;span class=&quot;s4&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;];&lt;br /&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;s3&quot;&gt;_bar&lt;/span&gt;.&lt;span class=&quot;s5&quot;&gt;items&lt;/span&gt; = itms; &amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;s3&quot;&gt;_bar&lt;/span&gt;.&lt;span class=&quot;s5&quot;&gt;selectedItem&lt;/span&gt; = [itms &lt;span class=&quot;s6&quot;&gt;objectAtIndex&lt;/span&gt;:&lt;span class=&quot;s7&quot;&gt;0&lt;/span&gt;];&lt;br /&gt;&lt;span class=&quot;s4&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;_bar&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s5&quot;&gt;autoresizingMask&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt; = &lt;/span&gt;UIViewAutoresizingFlexibleWidth;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;s5&quot;&gt;UIViewController&lt;/span&gt; *firstVC = [&lt;span class=&quot;s3&quot;&gt;_viewControllers&lt;/span&gt; &lt;span class=&quot;s6&quot;&gt;objectAtIndex&lt;/span&gt;:&lt;span class=&quot;s7&quot;&gt;0&lt;/span&gt;];&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;firstVC.&lt;span class=&quot;s5&quot;&gt;view&lt;/span&gt;.&lt;span class=&quot;s5&quot;&gt;frame&lt;/span&gt; = [&lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;s8&quot;&gt;subviewFrame&lt;/span&gt;];&lt;br /&gt;&lt;span class=&quot;s4&quot;&gt;&amp;nbsp; &amp;nbsp; firstVC.&lt;/span&gt;&lt;span class=&quot;s5&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s5&quot;&gt;autoresizingMask&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt; = &lt;/span&gt;UIViewAutoresizingFlexibleWidth&lt;span class=&quot;s4&quot;&gt; | &lt;/span&gt;UIViewAutoresizingFlexibleHeight&lt;span class=&quot;s4&quot;&gt;;&lt;br /&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;[&lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;s5&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;s6&quot;&gt;addSubview&lt;/span&gt;:firstVC.&lt;span class=&quot;s5&quot;&gt;view&lt;/span&gt;];&lt;br /&gt;}&lt;br /&gt;-(&lt;span class=&quot;s2&quot;&gt;void&lt;/span&gt;) viewDidLoad {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;s3&quot;&gt;bar&lt;/span&gt; = [[&lt;span class=&quot;s5&quot;&gt;UITabBar&lt;/span&gt; &lt;span class=&quot;s6&quot;&gt;alloc&lt;/span&gt;] &lt;span class=&quot;s6&quot;&gt;initWithFrame&lt;/span&gt;:&lt;span class=&quot;s6&quot;&gt;CGRectMake&lt;/span&gt;(&lt;span class=&quot;s7&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;s7&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;s5&quot;&gt;view&lt;/span&gt;.&lt;span class=&quot;s5&quot;&gt;frame&lt;/span&gt;.&lt;span class=&quot;s5&quot;&gt;size&lt;/span&gt;.&lt;span class=&quot;s5&quot;&gt;width&lt;/span&gt;, &lt;span class=&quot;s7&quot;&gt;30&lt;/span&gt;) ];&lt;br /&gt;&lt;span class=&quot;s4&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;(&lt;/span&gt;UIViewController&lt;span class=&quot;s4&quot;&gt; *vc &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;_viewControllers&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;) {&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt; &lt;/span&gt;addChildViewController&lt;span class=&quot;s4&quot;&gt;:vc];&lt;br /&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;s3&quot;&gt;_bar&lt;/span&gt;.&lt;span class=&quot;s5&quot;&gt;delegate&lt;/span&gt; = &lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;[&lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;s5&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;s6&quot;&gt;addSubview&lt;/span&gt;:&lt;span class=&quot;s3&quot;&gt;_bar&lt;/span&gt;];&lt;br /&gt;&lt;span class=&quot;s4&quot;&gt;&amp;nbsp; &amp;nbsp; [&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt; &lt;/span&gt;reloadBarInfo&lt;span class=&quot;s4&quot;&gt;];&lt;br /&gt;&lt;/span&gt;}&lt;br /&gt;-(&lt;span class=&quot;s2&quot;&gt;void&lt;/span&gt;) tabBar:(&lt;span class=&quot;s5&quot;&gt;UITabBar&lt;/span&gt; *)tabBar didSelectItem:(&lt;span class=&quot;s5&quot;&gt;UITabBarItem&lt;/span&gt; *)item&amp;nbsp;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;s2&quot;&gt;int&lt;/span&gt; idx = [&lt;span class=&quot;s3&quot;&gt;_bar&lt;/span&gt;.&lt;span class=&quot;s5&quot;&gt;items&lt;/span&gt; &lt;span class=&quot;s6&quot;&gt;indexOfObject&lt;/span&gt;:item];&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;s5&quot;&gt;UIViewController&lt;/span&gt; *newVC = [&lt;span class=&quot;s3&quot;&gt;_viewControllers&lt;/span&gt; &lt;span class=&quot;s6&quot;&gt;objectAtIndex&lt;/span&gt;:idx];&lt;br /&gt;&lt;span class=&quot;s4&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s5&quot;&gt;UIViewController&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt; *curVC = [&lt;/span&gt;_viewControllers&lt;span class=&quot;s4&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s6&quot;&gt;objectAtIndex&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;:&lt;/span&gt;_selectedIndex&lt;span class=&quot;s4&quot;&gt;];&lt;br /&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;s2&quot;&gt;if&lt;/span&gt;(newVC == curVC) {&lt;br /&gt;&lt;span class=&quot;s4&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;; &lt;/span&gt;// Don't switch - same one selected!&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span class=&quot;s4&quot;&gt;&amp;nbsp; &amp;nbsp; [curVC.&lt;/span&gt;&lt;span class=&quot;s5&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt; &lt;/span&gt;removeFromSuperview&lt;span class=&quot;s4&quot;&gt;];&lt;br /&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;newVC.&lt;span class=&quot;s5&quot;&gt;view&lt;/span&gt;.&lt;span class=&quot;s5&quot;&gt;frame&lt;/span&gt; = [&lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;s8&quot;&gt;subviewFrame&lt;/span&gt;];&lt;br /&gt;&lt;span class=&quot;s4&quot;&gt;&amp;nbsp; &amp;nbsp; newVC.&lt;/span&gt;&lt;span class=&quot;s5&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s5&quot;&gt;autoresizingMask&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt; = &lt;/span&gt;UIViewAutoresizingFlexibleWidth&lt;span class=&quot;s4&quot;&gt; | &lt;/span&gt;UIViewAutoresizingFlexibleHeight&lt;span class=&quot;s4&quot;&gt;;&lt;br /&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;[&lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;s5&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;s6&quot;&gt;addSubview&lt;/span&gt;:newVC.&lt;span class=&quot;s5&quot;&gt;view&lt;/span&gt;];&lt;br /&gt;&lt;span class=&quot;s4&quot;&gt;&amp;nbsp; &amp;nbsp; [&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt; &lt;/span&gt;transitionFromViewController&lt;span class=&quot;s4&quot;&gt;:curVC &lt;/span&gt;toViewController&lt;span class=&quot;s4&quot;&gt;:newVC &lt;/span&gt;duration&lt;span class=&quot;s4&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt; &lt;/span&gt;options&lt;span class=&quot;s4&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt; &lt;/span&gt;animations&lt;span class=&quot;s4&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt; &lt;/span&gt;completion&lt;span class=&quot;s4&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;];&lt;br /&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class=&quot;s2&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;s3&quot;&gt;selectedIndex&lt;/span&gt; = idx;&lt;br /&gt;}&lt;br /&gt;@end&lt;/pre&gt;
&lt;p class=&quot;p1&quot;&gt;And there you have it!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Thu, 10 May 2012 20:51:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/351</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/351</guid>
    </item>
    <item>
      <title>Super Fuzzy Searching on PostgreSQL</title>
      <description>&lt;p&gt;I have been working on doing some fuzzy searching on PostgreSQL for a while, and thought I'd share some of my experiences here.&amp;nbsp; Many people are not yet aware of the incredible fuzzy search capabilities of PostgreSQL, especially that were added in the 9.1 release.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Most people use an external engine such as Lucene to do fuzzy searches.&amp;nbsp; While, as you will see, there are still reasons to do so, they are much fewer now than they used to be.&lt;/p&gt;
&lt;h4&gt;Fuzzy Search Using Trigrams&lt;/h4&gt;
&lt;p&gt;While PostgreSQL has lots of different fuzzy search options (soundex, levenshtein, etc.), the one which has the most support is trigram searching.&amp;nbsp; What is a trigram?&amp;nbsp; Trigrams break a word up into 3-letter sequences, which can then be used to do similarity matches.&amp;nbsp; Think of the word &quot;hello&quot;.&amp;nbsp; It has the following trigrams: &quot;h&quot;, &quot;he&quot;, &quot;hel&quot;, &quot;ell&quot;, &quot;llo&quot;, &quot;lo&quot;, and &quot;o&quot;.&amp;nbsp; Now look at the word &quot;hallo&quot;.&amp;nbsp; It has the following trigrams: &quot;h&quot;, &quot;ha&quot;, &quot;hal&quot;, &quot;all&quot;, &quot;llo&quot;, &quot;lo&quot;, and &quot;o&quot;.&amp;nbsp; You can see that there are several trigrams that match, and several that don't match.&amp;nbsp; Similarity is computed via &lt;a href=&quot;http://en.wikipedia.org/wiki/Cosine_similarity&quot; target=&quot;_blank&quot;&gt;cosine similarity&lt;/a&gt; (which I don't totally understand), but, basically, the more trigrams you have in common the closer the match.&amp;nbsp; In the present case, 'hallo' and 'hello' have a similarity of 0.333333.&amp;nbsp; You can see this in PostgreSQL by saying:&lt;/p&gt;
&lt;pre&gt;select similarity('hello', 'hallo')&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;PostgreSQL also has two other relevant operators that use similarity - the &quot;&amp;lt;-&amp;gt;&quot; operator and the &quot;%&quot; operator.&amp;nbsp; &quot;&amp;lt;-&amp;gt;&quot; is the &quot;distance&quot; operator, which is simply one minus the similarity (i.e. if the similarity is 0.2 the distance will be 0.8).&amp;nbsp; For text searching, &quot;%&quot; is the &quot;similar&quot; operator, which returns true if two strings are similar, or false if they are not.&amp;nbsp; Two strings are defined as &quot;similar&quot; if their similarity is 0.3 or greater.&amp;nbsp; This can be set with set_limit(), but it is not usually useful to do so (we will deal with custom similarities later).&amp;nbsp; The &quot;%&quot; operator is important, because of its heavy use in indexing.&lt;/p&gt;
&lt;h4&gt;Installing Trigrams&lt;/h4&gt;
&lt;p&gt;The trigram module (&lt;a href=&quot;http://www.postgresql.org/docs/9.1/interactive/pgtrgm.html&quot; target=&quot;_blank&quot;&gt;pg_trgm&lt;/a&gt;) is not installed by default in PostgreSQL, but is one of their standard (and supported!) extensions.&amp;nbsp; To install, you need to make sure you build the module in the source code.&amp;nbsp; To do this, go into the contrib/pg_trgm directory of the source code and do a &quot;make; make install&quot;.&amp;nbsp; This will install the plugin, but will not activate it.&amp;nbsp; Then, in any database you want to use this plugin, put in the command:&lt;/p&gt;
&lt;pre&gt;CREATE EXTENSION pg_trgm;&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;This will load the necessary SQL to install the functions and operators needed to make trigrams work.&amp;nbsp; If you type that command in the template1 database, then all future databases created on that system will have the extension installed.&lt;/p&gt;
&lt;h4&gt;Using Trigrams Without an Index&lt;/h4&gt;
&lt;p&gt;The simplest use of trigrams would be to have a table with a name column, and do a search like this:&lt;/p&gt;
&lt;pre&gt;SELECT * FROM people WHERE lastname % 'Schmoe'&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;This will return a list of people where the trigram similarity is greater than the default threshold.&amp;nbsp; If you want to specify the similarity you are looking for, you can change that to:&lt;/p&gt;
&lt;pre&gt;SELECT * FROM people WHERE similarity(lastname, 'Schmoe') &amp;gt; 0.5&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;This will give a less-tolerant match than the default.&lt;/p&gt;
&lt;p&gt;The problem with doing this is that it takes a lot of processing power.&amp;nbsp; The reason people usually use databases is because they have a huge number of records and need to be able to search them quickly.&amp;nbsp; If we have 10,000 records, manually doing trigram matches will take quite a bit of time.&lt;/p&gt;
&lt;p&gt;So, one of the best features of PostgreSQL 9.1 is the ability for PostgreSQL to incorporate trigrams into an index.&amp;nbsp; So, to make an index to speed up our search, do:&lt;/p&gt;
&lt;pre&gt;CREATE INDEX people_lastname_trigram_idx ON people USING gist(lastname gist_trgm_ops);&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;This will create a &quot;gist&quot; index, which is a special type of index which is often used in spacial and other vector-oriented matching.&amp;nbsp; The &quot;gist_trgm_ops&quot; is a little bit of magic that tells gist how to use a text field as a vector of trigrams.&lt;/p&gt;
&lt;p&gt;Now, your query will use the index, provided you have enough rows to make it worthwhile.&amp;nbsp; HOWEVER, it is not yet using the index efficiently.&amp;nbsp; While PostgreSQL &lt;em&gt;can&lt;/em&gt; (and will) use the index for this query, it doesn't actually check the condition until a later step (I believe, but am not sure, that it is using the index to get everything in the right order, and then at a later stage doing filtering).&amp;nbsp; For large tables, this can still be several orders of magnitude worse than you want.&amp;nbsp; To fix this, you MUST use the &quot;%&quot; operator.&amp;nbsp; This will cause the index to have an &quot;index condition&quot;, which it will use to limit the results that it puts out.&amp;nbsp; So, if you have:&lt;/p&gt;
&lt;pre&gt;SELECT * FROM people WHERE lastname % 'Schmoe';&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;This will use the index AND the index condition, and will be super-fast (except in extremely large datasets - see next section).&amp;nbsp; However, this uses the built-in cutoff point of 0.3 similarity.&amp;nbsp; What if I want my results to be tighter than that?&amp;nbsp; The best way is to combine % with similarity(), like this:&lt;/p&gt;
&lt;pre&gt;SELECT * FROM people WHERE lastname % 'Schmoe' AND similarity(lastname, 'Schmoe') &amp;gt; 0.5;&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;In this case, the database will use the &quot;%&quot; condition for the index, which will be incredibly fast, and the &quot;similarity()&quot; call as a post-index filter, which, since there is a much smaller dataset, will still be pretty fast.&lt;/p&gt;
&lt;h4&gt;Working With Larger Datasets&lt;/h4&gt;
&lt;p&gt;I had trouble working with trigrams because my main dataset is about 14 million titles.&amp;nbsp; At this size, trigram searching is really slow.&amp;nbsp; With the whole database loaded in-memory (either in PG's cache or in the filesystem cache - I have many, many gigs of memory), a trigram search of the database &lt;em&gt;USING THE INDEX&lt;/em&gt; took between 3 and 12 seconds, depending on the string.&amp;nbsp; Poking around, I came out with the following basic results for a database on an Amazon EC2 4XL instance without any other load:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;100,000 records: 40 milliseconds&lt;/li&gt;
&lt;li&gt;1,000,000 records: 0.4 seconds&lt;/li&gt;
&lt;li&gt;14,000,000 records: 7 seconds&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, as you can see, the useful limit to these queries is about 1 million records.&amp;nbsp; Therefore, if you have more than 14 million rows, if you want to do trigrams, you need to find a way to boost performance.&amp;nbsp; I've found there are two basic methods you can use to speed up trigrams on large datasets:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create specialized indexes with subsets of your data&lt;/li&gt;
&lt;li&gt;Create a separate wordlist table with unique words&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;#1 is much preferred if you can do it, because it is an entirely database-oriented method.&amp;nbsp; Basically, what I did, is I figured out that on my queries I only needed to trigram search on about 1 million of my 14 million records.&amp;nbsp; Therefore, I specialized the index by adding a &quot;WHERE&quot; clause to the index itself.&amp;nbsp; On my database, I have a &quot;type&quot; field, and I'm only searching certain types of records.&amp;nbsp; Therefore, I changed my index to the following:&lt;/p&gt;
&lt;pre&gt;CREATE INDEX people_lastname_restricted_trigram_idx ON people USING gist(lastname gist_trgm_ops) WHERE type IN ('my_type1', 'my_type2');&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;This meant that only about a million records were being stored in the index, which brought down my search time considerably.&amp;nbsp; Another search that I was doing was based on the person's &quot;popularity&quot;, in which case, I added another index for popularity being greater than 20.&amp;nbsp; This restricted the set down to about 100,000 records, which made it blazingly fast.&lt;/p&gt;
&lt;p&gt;The other alternative (#2) I mentioned is to create a separate table of words which is searched.&amp;nbsp; The idea is that while you may have 14 million records, there probably aren't 14 million words.&amp;nbsp; Therefore, you create a table using unique words from the database, and then add a trigram index on that.&amp;nbsp; The problem, though, is that this takes either (a) a lot of manual work, or (b) a lot of triggers, none of which is the way I like to administer databases.&amp;nbsp; Nonetheless, it can work if you are merely wanting to use trigrams to fuzzy-match individual words.&amp;nbsp; It can be especially helpful in conjunction with PostgreSQL's &lt;a href=&quot;http://www.postgresql.org/docs/9.1/interactive/textsearch.html&quot; target=&quot;_blank&quot;&gt;full-text search&lt;/a&gt; (previously known as tsearch2), which still operates blazingly-fast on 14 million records.&amp;nbsp; Fuzzy string matching on words can be combined with full-text search on records to present a powerful and fast method of searching.&amp;nbsp;&amp;nbsp; The wordlist can be fuzzy-matched to provide better hints at what words are in the fulltext.&lt;/p&gt;
&lt;p&gt;To create a wordlist, do something like this:&lt;/p&gt;
&lt;pre&gt;CREATE TABLE search_words (word text);&lt;br /&gt;CREATE INDEX search_words_word_trigram_idx ON search_words USING gist(word gist_trgm_ops);&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;Then, every time you need to regenerate your wordlist, do the following:&lt;/p&gt;
&lt;pre&gt;DELETE FROM search_words;&lt;br /&gt;INSERT INTO search_words (word) SELECT DISTINCT lower(word) FROM (SELECT unnest(regexp_split_to_array(lastname, E'\\\\W+')) AS word FROM people) words WHERE word IS NOT NULL AND length(word) &amp;gt; 3;&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;What that does is explode the lastname field out into words (in case a lastname is multi-word), where each word is its own record.&amp;nbsp; It also filters out excessively short words (optional).&amp;nbsp; It then inserts these into the search_words table, which has a trigram index.&amp;nbsp; So, now, if you want to fuzzy-match individual words, you can use the search_words table!&lt;/p&gt;
&lt;p&gt;Anyway, additional fun can be had by using unaccent to remove accents before all of this processing, or other fun to massage your data however you feel is best.&amp;nbsp; The important thing is that, for all but the most strenuous data sets, we can now keep all of the searching located within the database itself, managed by database tools, without having to rely on external search engines such as Lucene, which take time, management, machine power, and their own sets of headaches.&amp;nbsp; Lucene itself &lt;a href=&quot;http://www.nearinfinity.com/blogs/aaron_mccurry/what_happens_to_lucene_when.html&quot; target=&quot;_blank&quot;&gt;often has to be hand-rigged for large datasets even&lt;/a&gt;.&amp;nbsp; I am a big believer in pushing as much data work to the database as possible, and PostgreSQL keeps pushing the bar higher!&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Thu, 12 Jan 2012 16:58:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/350</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/350</guid>
    </item>
    <item>
      <title>Enjoy Skyrim's Alchemy?  Check Out Nature's Own Alchemy System</title>
      <description>&lt;p&gt;If you have played The Elder Scrolls V: Skyrim, you have probably made use of their &quot;alchemy&quot; system. &amp;nbsp;What you may not have known is that this is based, in some degree, on the real-life practices of both ancient and modern herbalists, who combine herbs and herbal actions to produce desired effects on the body and the body's health. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you are interested in learning more, you should check out &lt;a href=&quot;http://itunes.apple.com/app/the-herbalist/id489767701&quot; target=&quot;_blank&quot;&gt;The Herbalist&lt;/a&gt;, a new iPhone/iPad/iPod/iOS app which describes a number of herbs and the actions that herbalists use them for. &amp;nbsp;In addition, you can even search the herbal database by the action you are looking for or by the specific malady for which it is often used. &amp;nbsp;It also includes information on different ways of preparing herbs for usage in tinctures, oils, infusions, lotions, and other preparations.&lt;/p&gt;
&lt;p&gt;Anyway, if you enjoy Skyrim's alchemy, you'll love seeing how practicing herbalists make use of the same basic ideas.&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Thu, 22 Dec 2011 23:55:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/349</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/349</guid>
    </item>
    <item>
      <title>Misc stuff I found out</title>
      <description>&lt;p&gt;Objective-C PostgreSQL stuff:&lt;/p&gt;
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/objectivepq/source/checkout&quot; target=&quot;_blank&quot;&gt;ObjectivePQ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.postgresqlformac.com/&quot; target=&quot;_blank&quot;&gt;PostgreSQL For Mac&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/postgres-kit/&quot; target=&quot;_blank&quot;&gt;Postgres-Kit&lt;/a&gt;&amp;nbsp;(includes a solution for embedding a PostgreSQL database *in* your app)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sourceforge.net/projects/pgsqlcocoa/&quot; target=&quot;_blank&quot;&gt;pgsqlcocoa&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bitbucket.org/mka/baseten/wiki/Home&quot; target=&quot;_blank&quot;&gt;BaseTen&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;Misc:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/entropydb/&quot; target=&quot;_blank&quot;&gt;EntropyDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.slideshare.net/guest9efd1a1/building-server-applications-using-objectivec-and-gnustep&quot; target=&quot;_blank&quot;&gt;Building Server Applications Using Objective-C and GNUstep&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/714100/os-detecting-makefile&quot; target=&quot;_blank&quot;&gt;How to detect the OS in a Makefile&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;Building a shared library on OSX: (see &lt;a href=&quot;http://www.finkproject.org/doc/porting/shared.php&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;):&lt;/div&gt;
&lt;/div&gt;
&lt;pre&gt;gcc -dynamiclib -install_name /usr/local/lib/libfoo.2.dylib &amp;nbsp;-compatibility_version 2.4 -current_version 2.4.5 -o libfoo.2.4.5.dylib source.o code.o&lt;/pre&gt;
&lt;p&gt;I have also seen the options&amp;nbsp;-undefined suppress -flat_namespace &lt;a href=&quot;http://stackoverflow.com/questions/3532589/how-to-build-a-dylib-from-several-o-in-mac-os-x-using-gcc&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Another &lt;a href=&quot;http://qin.laya.com/tech_coding_help/dylib_linking.html&quot; target=&quot;_blank&quot;&gt;dylib link&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://g4u0419c.houston.hp.com/en/B2355-90655/ch05s11.html&quot; target=&quot;_blank&quot;&gt;Caution mixing shared and archive libs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Seth Godin - &lt;a href=&quot;http://sethgodin.typepad.com/seths_blog/2005/11/how_to_run_a_us.html&quot; target=&quot;_blank&quot;&gt;how to run a useless conference&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Sun, 26 Jun 2011 19:56:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/342</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/342</guid>
    </item>
    <item>
      <title>Introducing Newm: An Objective-C Framework for Web Applications</title>
      <description>&lt;p&gt;I am working on starting a web application framework called &lt;a href=&quot;https://github.com/johnnyb/Newm&quot; target=&quot;_blank&quot;&gt;Newm&lt;/a&gt;. It is kind of like an Objective-C-on-Rails. &amp;nbsp;&lt;a href=&quot;https://github.com/johnnyb/Newm&quot; target=&quot;_blank&quot;&gt;Check it out&lt;/a&gt;!&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Tue, 21 Jun 2011 11:48:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/341</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/341</guid>
    </item>
    <item>
      <title>Objective-C Hackery</title>
      <description>&lt;p&gt;Been working on several objective-c projects.&amp;nbsp; I love to get into the fun tricks you can do with languages and stuff.&amp;nbsp; Here's some interesting tidbits I found:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/25746/whats-the-difference-between-a-string-constant-and-a-string-literal&quot; target=&quot;_blank&quot;&gt;Global string constants versus string literals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://developer.apple.com/library/ios/#DOCUMENTATION/Cocoa/Conceptual/CocoaFundamentals/AddingBehaviortoaCocoaProgram/AddingBehaviorCocoa.html&quot; target=&quot;_blank&quot;&gt;Cocoa fundamentals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://developer.apple.com/library/ios/#DOCUMENTATION/Cocoa/Conceptual/Strings/introStrings.html#//apple_ref/doc/uid/10000035i&quot; target=&quot;_blank&quot;&gt;Cocoa string programming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.geekhideout.com/urlcode.shtml&quot; target=&quot;_blank&quot;&gt;URLEncode/Decode in C&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.faqs.org/docs/Linux-HOWTO/Program-Library-HOWTO.html#INIT-AND-CLEANUP&quot; target=&quot;_blank&quot;&gt;How to write code that executes *BEFORE* main() is called&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.mentalcases.net/texts/security/TextSectionStudy.txt&quot; target=&quot;_blank&quot;&gt;A study of ELF .text sections&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.haible.de/bruno/documentation/ffcall/callback/callback.html&quot; target=&quot;_blank&quot;&gt;Closures in C?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://thirdcog.eu/pwcblocks/&quot; target=&quot;_blank&quot;&gt;Introduction to C Blocks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html#Common-Predefined-Macros&quot; target=&quot;_blank&quot;&gt;gcc predefined macros&lt;/a&gt; (__COUNTER__ is cool)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/992070/static-constructor-equivalent-in-objective-c&quot; target=&quot;_blank&quot;&gt;Class initialization in Objective C using +initialize&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/5012935/static-initializers-in-objective-c&quot; target=&quot;_blank&quot;&gt;Static initializers for heap-based objects?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://osmorphis.blogspot.com/2009/02/objective-c-initializer-patterns_2937.html&quot; target=&quot;_blank&quot;&gt;Objective C initializers important patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html&quot; target=&quot;_blank&quot;&gt;The Objective C runtime reference (always useful)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/4864866/c-c-with-gcc-statically-add-resource-files-to-executable-library&quot; target=&quot;_blank&quot;&gt;Add resources to binary (1)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/1997172/is-there-a-linux-equivalent-of-windows-resource-files&quot; target=&quot;_blank&quot;&gt;Add resources to binary (2)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/1656968/platform-independant-resource-management&quot; target=&quot;_blank&quot;&gt;Add resources to binary (3)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.linuxjournal.com/content/embedding-file-executable-aka-hello-world-version-5967&quot; target=&quot;_blank&quot;&gt;Add resources to binary (4)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Sat, 18 Jun 2011 17:55:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/340</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/340</guid>
    </item>
    <item>
      <title>Miscellaneous RFID Links</title>
      <description>&lt;p&gt;Learning RFID for a project I'm going to work on soon.&amp;nbsp; Here are some handy dandy links!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://tenderlovemaking.com/2009/09/19/ruby-and-rfid-tags/&quot; target=&quot;_blank&quot;&gt;Using RFID tags with Ruby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.libnfc.org/documentation/introduction&quot; target=&quot;_blank&quot;&gt;libnfc - free RFID reading library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.smartlab.deusto.es/java-rfid/&quot; target=&quot;_blank&quot;&gt;Java-based RFID developer kit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Radio-frequency_identification&quot; target=&quot;_blank&quot;&gt;Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rfid-in-china.com/products_702_1.html&quot; target=&quot;_blank&quot;&gt;Long-range RFID readers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.gaorfidassettracking.com/RFID_Asset_Tracking_Resources/rfid_understanding/&quot; target=&quot;_blank&quot;&gt;Other interesting stuff&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.iautomate.com/products/Wavetrend-L%252dRX201-Long-Range-RFID-Reader.html&quot; target=&quot;_blank&quot;&gt;Long-Range RFID reader with development kit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.aliexpress.com/product-fm/320979826-UHF-RFID-Long-Range-Reader-4-port--wholesalers.html&quot; target=&quot;_blank&quot;&gt;Another reader&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rfid-in-china.com/2011-03-20/products_detail_2328.html&quot; target=&quot;_blank&quot;&gt;Another reader&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>JB</author>
      <pubDate>Tue, 07 Jun 2011 02:47:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/339</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/339</guid>
    </item>
    <item>
      <title>Ideas 2011-05-25</title>
      <description>&lt;p&gt;Had some thoughts today, thought I'd write them down:&lt;/p&gt;
&lt;p&gt;Been looking at Google refine.&amp;nbsp; Some of this is pretty obvious, but I'm thinking it would be pretty awesome to port this to use on a database backend.&amp;nbsp; Basically, do the transforms on the data in the database, and, if you want, it will serialize it back out to a new table, or replace the existing one.&lt;/p&gt;
&lt;p&gt;What would also be cool is a generalized report generator for Rails, possibly using AREL.&amp;nbsp; You could do security by defining mandatory filters for tables, limiting the tables/columns, and other things.&amp;nbsp; It could predict the time the report will take to run by using PostgreSQL's &quot;explain&quot; command.&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Wed, 25 May 2011 19:18:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/337</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/337</guid>
    </item>
    <item>
      <title>Database Scaling with PostgreSQL</title>
      <description>&lt;p&gt;I've been digging around on various database scaling options for PostgreSQL. &amp;nbsp;Here's some interesting links I've stumbled upon:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://s3.amazonaws.com/lcp/porras/myfiles/ror_db_balancing.html&quot; target=&quot;_blank&quot;&gt;Runtime selection of databases&lt;/a&gt; (for selecting between readonly and readwrite databases)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.postgresql.org/docs/9.0/interactive/hot-standby.html&quot; target=&quot;_blank&quot;&gt;Hot standby in PostgreSQL&lt;/a&gt;&amp;nbsp;and &lt;a href=&quot;http://www.postgresql.org/docs/9.0/static/warm-standby.html&quot; target=&quot;_blank&quot;&gt;log-shipping/streaming&lt;/a&gt; (and&lt;a href=&quot;http://wiki.postgresql.org/wiki/Binary_Replication_Tutorial&quot; target=&quot;_blank&quot;&gt; a tutorial&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A &lt;a href=&quot;https://github.com/technoweenie/masochism&quot;&gt;Rails mechanism for sending write requests to a separate server than read requests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Sharding Links:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://highscalability.com/unorthodox-approach-database-design-coming-shard&quot; target=&quot;_blank&quot;&gt;Introduction to sharding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://tech.myemma.com/managing-sequences-sharded-environment/&quot; target=&quot;_blank&quot;&gt;Sequence Management with Postgres Sharding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.postgresqlconference.org/content/practical-postgres-sharding-scaling-horizon&quot; target=&quot;_blank&quot;&gt;PostgreSQL sharding on Pandora&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/994882/what-is-a-good-way-to-horizontal-shard-in-postgresql&quot; target=&quot;_blank&quot;&gt;Interesting PostgreSQL partitioning features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.postgresqlconference.org/sites/default/files/ScalingWithGridSQL.odp&quot; target=&quot;_blank&quot;&gt;GridSQL stuff&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.gluster.org/&quot; target=&quot;_blank&quot;&gt;Gluster&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>JB</author>
      <pubDate>Tue, 24 May 2011 02:35:00 +0000</pubDate>
      <link>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/336</link>
      <guid>http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/336</guid>
    </item>
  </channel>
</rss>
