<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>State Of Flux - Home</title>
  <id>tag:stateofflux.com,2008:mephisto/</id>
  <generator version="0.8.0" uri="http://mephistoblog.com">Mephisto Drax</generator>
  <link href="http://stateofflux.com/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://stateofflux.com/" rel="alternate" type="text/html"/>
  <updated>2008-07-14T11:05:14Z</updated>
  <entry xml:base="http://stateofflux.com/">
    <author>
      <name>mark</name>
    </author>
    <id>tag:stateofflux.com,2008-07-14:27</id>
    <published>2008-07-14T11:05:00Z</published>
    <updated>2008-07-14T11:05:14Z</updated>
    <category term="404"/>
    <category term="500"/>
    <category term="apache"/>
    <category term="errorpages"/>
    <category term="layout"/>
    <category term="nginx"/>
    <category term="rails"/>
    <category term="rake"/>
    <category term="static"/>
    <link href="http://stateofflux.com/2008/7/14/generate-static-pages-in-rails" rel="alternate" type="text/html"/>
    <title>Generate static pages in Rails</title>
<content type="html">
            &lt;p&gt;I wanted a nice looking 404, 500 and maintenance pages for my Rails app and I couldn&#8217;t serve them from Rails.&lt;/p&gt;


My requirements were:
	&lt;ul&gt;
	&lt;li&gt;I didn&#8217;t want to hand code the pages &#8211; I&#8217;m using a web framework for a reason!&lt;/li&gt;
		&lt;li&gt;I wanted to use the application&#8217;s layout&lt;/li&gt;
		&lt;li&gt;I needed that pages to be static so I could serve them when the Rails app was either down or when it had &#8216;issues&#8217;&lt;/li&gt;
	&lt;/ul&gt;


My solution was to:
	&lt;ol&gt;
	&lt;li&gt;create a controller for the purpose of rendering the static pages&lt;/li&gt;
		&lt;li&gt;tailor your views so you have nice 404, 500 and maintenance pages&lt;/li&gt;
		&lt;li&gt;modify the layout so that signin and register were not longer present&lt;/li&gt;
		&lt;li&gt;create a rake task to render the pages and write them out to a file&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Items 1 &#38; 2 are just standard Rails stuff &#8211; so go nutz young coders.&lt;/p&gt;


Item 3 was pretty straight forward, in the layout I put:
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;  &lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;unless&lt;/span&gt; controller.controller_name == &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;errors&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;     put your sign-in code here&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Item 4 was a bit trickier, but this rake task should get you up and running.&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;  namespace &lt;span class=&quot;sy&quot;&gt;:generate&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    task &lt;span class=&quot;sy&quot;&gt;:pages&lt;/span&gt; =&amp;gt; &lt;span class=&quot;sy&quot;&gt;:environment&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;action_controller/integration&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      app = &lt;span class=&quot;co&quot;&gt;ActionController&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Integration&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Session&lt;/span&gt;.new&lt;tt&gt;
&lt;/tt&gt;      app.host! &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;stateofflux.com&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      [[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/errors/error_404&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;public/40 4.html&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;       [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/errors/error_500&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;public/500.html&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]].each &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |url, file|&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;begin&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;          app.get url&lt;tt&gt;
&lt;/tt&gt;          &lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.open(file, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) { |f| f.write app.response.body }&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;Exception&lt;/span&gt; =&amp;gt; e&lt;tt&gt;
&lt;/tt&gt;          puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Could not write file &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;e&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;We run the rake task in the development environment then check it in, but you could run it in production if there was production data that you needed to create the page.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://stateofflux.com/">
    <author>
      <name>mark</name>
    </author>
    <id>tag:stateofflux.com,2008-07-13:26</id>
    <published>2008-07-13T01:20:00Z</published>
    <updated>2008-07-13T01:21:17Z</updated>
    <category term="activerecord"/>
    <category term="pg"/>
    <category term="postgres"/>
    <category term="postgresql"/>
    <category term="rails"/>
    <link href="http://stateofflux.com/2008/7/13/activerecord-postgresql-adapter-in-rails-2-1" rel="alternate" type="text/html"/>
    <title>activerecord-postgresql-adapter in Rails 2.1</title>
<content type="html">
            If you get the following message
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;Please install the postgresql adapter: `gem install activerecord-postgresql-adapter` &lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


It means you don&#8217;t have the new &#8216;pg&#8217; postgresql library installed.  This is easily fixed with a bit of 
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;sudo gem install pg&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
          </content>  </entry>
  <entry xml:base="http://stateofflux.com/">
    <author>
      <name>mark</name>
    </author>
    <id>tag:stateofflux.com,2008-06-14:25</id>
    <published>2008-06-14T04:49:00Z</published>
    <updated>2008-06-14T04:51:05Z</updated>
    <category term="column"/>
    <category term="cua"/>
    <category term="cua-mode"/>
    <category term="editing"/>
    <category term="emacs"/>
    <category term="textmate"/>
    <link href="http://stateofflux.com/2008/6/14/column-editing-with-emacs" rel="alternate" type="text/html"/>
    <title>Column editing with Emacs</title>
<content type="html">
            &amp;lt;object height=&quot;300&quot; width=&quot;400&quot;&gt;    &amp;lt;param /&gt;    &amp;lt;param /&gt;    &amp;lt;param /&gt;    &amp;lt;embed src=&quot;http://www.vimeo.com/moogaloop.swf?clip_id=1168225&amp;amp;amp;server=www.vimeo.com&amp;amp;amp;show_title=1&amp;amp;amp;show_byline=1&amp;amp;amp;show_portrait=0&amp;amp;amp;color=&amp;amp;amp;fullscreen=1&quot; height=&quot;300&quot; width=&quot;400&quot;&gt;&amp;lt;/embed&gt;&amp;lt;/object&gt;&lt;br /&gt;&lt;a href=&quot;http://www.vimeo.com/1168225?pg=embed&amp;amp;#38;sec=1168225&quot;&gt;Emacs Column Editing&lt;/a&gt; from &lt;a href=&quot;http://www.vimeo.com/user537893?pg=embed&amp;amp;#38;sec=1168225&quot;&gt;Mark Mansour&lt;/a&gt; on &lt;a href=&quot;http://vimeo.com?pg=embed&amp;amp;#38;sec=1168225&quot;&gt;Vimeo&lt;/a&gt;.

	&lt;p&gt;My &lt;span class=&quot;caps&quot;&gt;OS X&lt;/span&gt; lovin&#8217; buddies love to point out how easy it is to manipulate columns in &lt;a href=&quot;http://manual.macromates.com/en/working_with_text#column_selections&quot;&gt;TextMate&lt;/a&gt; .  But I&#8217;m old skool and I still love &lt;a href=&quot;http://www.gnu.org/software/emacs/&quot;&gt;emacs&lt;/a&gt; .  So to prove that column editing mode is a cinch I&#8217;ve put together my first screencast to demonstrate column editing mode in Emacs.  Emacs ships with &lt;a href=&quot;http://www.gnu.org/software/emacs/manual/html_node/emacs/CUA-Bindings.html&quot;&gt;&lt;span class=&quot;caps&quot;&gt;CUA&lt;/span&gt; mode&lt;/a&gt; which you need to turn on and then let the good times begin.  Enjoy&#8230;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://stateofflux.com/">
    <author>
      <name>mark</name>
    </author>
    <id>tag:stateofflux.com,2008-06-09:20</id>
    <published>2008-06-09T05:30:00Z</published>
    <updated>2008-06-09T05:30:36Z</updated>
    <category term="aggregate"/>
    <category term="denormalize"/>
    <category term="postgres"/>
    <category term="postgresql"/>
    <category term="sql"/>
    <link href="http://stateofflux.com/2008/6/9/cleaning-dirty-database-data" rel="alternate" type="text/html"/>
    <title>Cleaning dirty database data</title>
<content type="html">
            &lt;p&gt;I have a database with duplicate records in it and I want to know how many records I should have if I clean out the duplicates.  Boy is this thing &lt;strong&gt;dirty!&lt;/strong&gt;  The dataset I&#8217;m working with a mid sized (approximately 2 million records) and it&#8217;s a dump from another system.  One of the problems is that the data in the dump has been denormalized.  The second part of the problem is that some data has been entered multiple times in the source system&lt;sup&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;


Let me give you an example.  
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;blog_example=# \d&lt;tt&gt;
&lt;/tt&gt;              List of relations&lt;tt&gt;
&lt;/tt&gt; Schema |     Name      | Type  |    Owner    &lt;tt&gt;
&lt;/tt&gt;--------+---------------+-------+-------------&lt;tt&gt;
&lt;/tt&gt; public | addresses     | table | markmansour&lt;tt&gt;
&lt;/tt&gt; public | users         | table | markmansour&lt;tt&gt;
&lt;/tt&gt;(2 rows)&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

If I wanted to count the number of users, this would be straight forward, I&#8217;d just:
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;blog_example=# select count(*) from users;&lt;tt&gt;
&lt;/tt&gt; count &lt;tt&gt;
&lt;/tt&gt;-------&lt;tt&gt;
&lt;/tt&gt;     3&lt;tt&gt;
&lt;/tt&gt;(1 row)&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

But let&#8217;s look at the data a bit more closely.
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;blog_example=# select * from users;&lt;tt&gt;
&lt;/tt&gt; id | name  &lt;tt&gt;
&lt;/tt&gt;----+-------&lt;tt&gt;
&lt;/tt&gt;  1 | Korny&lt;tt&gt;
&lt;/tt&gt;  2 | Tim&lt;tt&gt;
&lt;/tt&gt;  3 | Korny&lt;tt&gt;
&lt;/tt&gt;(3 rows)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;blog_example=# select * from phone_numbers;&lt;tt&gt;
&lt;/tt&gt; id | user_id |  number  &lt;tt&gt;
&lt;/tt&gt;----+---------+----------&lt;tt&gt;
&lt;/tt&gt;  1 |       1 | 11111111&lt;tt&gt;
&lt;/tt&gt;  2 |       1 | 22222222&lt;tt&gt;
&lt;/tt&gt;  3 |       2 | 33333333&lt;tt&gt;
&lt;/tt&gt;  4 |       3 | 11111111&lt;tt&gt;
&lt;/tt&gt;  5 |       3 | 22222222&lt;tt&gt;
&lt;/tt&gt;(5 rows)&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

For the purposes of this example I&#8217;ll consider a duplicate to be a user with the exacly the same name, phone number and address &#8211; the main thing is that there are multiple one-to-many relationships and that there is repetition.  In this example the user Korny (users with the id 1 &#38; 3) have the same phone numbers and the same address and should be considered duplicates.  
In &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; the normal way to group things together is to use the cleverly named &#8220;group by&#8221; clause, but that doesn&#8217;t get us what we&#8217;re after&lt;sup&gt;&lt;a href=&quot;#fn2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.  I&#8217;d like to see the following:
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;blog_example=# magic select name, number but put the numbers on the same line&lt;tt&gt;
&lt;/tt&gt; name  |  number  &lt;tt&gt;
&lt;/tt&gt;-------+----------&lt;tt&gt;
&lt;/tt&gt; Korny | 11111111, 22222222&lt;tt&gt;
&lt;/tt&gt; Tim   | 33333333&lt;tt&gt;
&lt;/tt&gt;(2 rows)&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

This can be done with PostgreSql (if you know how to do this in MySql please let me know!) by &lt;a href=&quot;http://www.postgresql.org/docs/8.3/static/xaggr.html&quot;&gt;creating your own aggregate function&lt;/a&gt; .  You&#8217;ve probably used an aggregate function like &lt;span class=&quot;caps&quot;&gt;MAX&lt;/span&gt; or &lt;span class=&quot;caps&quot;&gt;AVG&lt;/span&gt; before.  I&#8217;m after a string aggregation function.  You can define one like this:
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;CREATE AGGREGATE array_accum_text (&lt;tt&gt;
&lt;/tt&gt;    basetype = text,&lt;tt&gt;
&lt;/tt&gt;    sfunc = array_append,&lt;tt&gt;
&lt;/tt&gt;    stype = text[],&lt;tt&gt;
&lt;/tt&gt;    initcond = '{}',&lt;tt&gt;
&lt;/tt&gt;    sortop = &amp;gt;);&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

This allows related rows to be grouped up, for example:
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;blog_example=# select u.*, array_to_string(array_accum_text(cast(ph.number as text)), ',') as all_phone_numbers&lt;tt&gt;
&lt;/tt&gt;blog_example=#   from users as u&lt;tt&gt;
&lt;/tt&gt;blog_example=#   inner join phone_numbers as ph on u.id = ph.user_id&lt;tt&gt;
&lt;/tt&gt;blog_example=#   group by u.id, u.name;&lt;tt&gt;
&lt;/tt&gt; id | name  | all_phone_numbers &lt;tt&gt;
&lt;/tt&gt;----+-------+-------------------&lt;tt&gt;
&lt;/tt&gt;  3 | Korny | 11111111,22222222&lt;tt&gt;
&lt;/tt&gt;  1 | Korny | 11111111,22222222&lt;tt&gt;
&lt;/tt&gt;  2 | Tim   | 33333333&lt;tt&gt;
&lt;/tt&gt;(3 rows)&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

To take it a step further we can now group related fields together, but I&#8217;ll do it via a view.  I want the users id to remain so that when I join the text together it doesn&#8217;t collapse all the telephone numbers from all the names even if their user ids are different (this is really hard to explain so I suggest trying it out without a view to see what I mean).
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;blog_example=# create view extended_users as&lt;tt&gt;
&lt;/tt&gt;blog_example-#   select u.id as user_id,&lt;tt&gt;
&lt;/tt&gt;blog_example-#          u.name as name, &lt;tt&gt;
&lt;/tt&gt;blog_example-#          array_to_string(array_accum_text(cast(ph.number as text)), ',') as all_phone_numbers&lt;tt&gt;
&lt;/tt&gt;blog_example-#     from users as u&lt;tt&gt;
&lt;/tt&gt;blog_example-#     inner join phone_numbers as ph on u.id = ph.user_id&lt;tt&gt;
&lt;/tt&gt;blog_example-#     group by u.id, u.name;&lt;tt&gt;
&lt;/tt&gt;CREATE VIEW&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;blog_example=# select name, all_phone_numbers from extended_users&lt;tt&gt;
&lt;/tt&gt;blog_example-#   group by name, all_phone_numbers;&lt;tt&gt;
&lt;/tt&gt; name  | all_phone_numbers &lt;tt&gt;
&lt;/tt&gt;-------+-------------------&lt;tt&gt;
&lt;/tt&gt; Korny | 11111111,22222222&lt;tt&gt;
&lt;/tt&gt; Tim   | 33333333&lt;tt&gt;
&lt;/tt&gt;(2 rows)&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

From this query I know that there are only two records once I remove all duplicates.  When I ran this over my dataset it took the rows from 2 million down to 1.4 million.  That is a lot of redundancy that my users don&#8217;t want to see.  My next action is going to be to writing some &lt;a href=&quot;http://api.rubyonrails.org/classes/ActiveRecord/Migration.html&quot;&gt;Rails migrations&lt;/a&gt; to clean it up :), but that will have to wait for another post.

	&lt;h3&gt;Footnotes&lt;/h3&gt;


	&lt;p&gt;&lt;sup&gt;1&lt;/sup&gt; I want to talk about a technical solution so let ignore the politics of the situation (i.e. let&#8217;s presume that I can&#8217;t get the data keyed in a better way or have the data delivered in a more normalized format).&lt;/p&gt;


	&lt;p&gt;&lt;sup&gt;2&lt;/sup&gt; Some &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt;:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;blog_example=# select u.name, ph.number from users as u&lt;tt&gt;
&lt;/tt&gt;blog_example-#        inner join phone_numbers as ph on u.id = ph.user_id&lt;tt&gt;
&lt;/tt&gt;blog_example-#        group by u.name, ph.number;&lt;tt&gt;
&lt;/tt&gt; name  |  number  &lt;tt&gt;
&lt;/tt&gt;-------+----------&lt;tt&gt;
&lt;/tt&gt; Korny | 11111111&lt;tt&gt;
&lt;/tt&gt; Korny | 22222222&lt;tt&gt;
&lt;/tt&gt; Tim   | 33333333&lt;tt&gt;
&lt;/tt&gt;(3 rows)&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
          </content>  </entry>
  <entry xml:base="http://stateofflux.com/">
    <author>
      <name>mark</name>
    </author>
    <id>tag:stateofflux.com,2008-03-24:18</id>
    <published>2008-03-24T00:43:00Z</published>
    <updated>2008-03-24T00:45:56Z</updated>
    <category term="australia"/>
    <category term="engineyard"/>
    <category term="evanphoneix"/>
    <category term="ezra"/>
    <category term="melbourne"/>
    <category term="rubinius"/>
    <category term="ruby"/>
    <link href="http://stateofflux.com/2008/3/24/rubinius-comes-to-melbourne" rel="alternate" type="text/html"/>
    <title>Rubinius comes to Melbourne</title>
<content type="html">
            &lt;p&gt;&lt;a href=&quot;http://rubini.us/&quot;&gt;Rubinius&lt;/a&gt; is a reimplementation of the &lt;a href=&quot;http://ruby-lang.org/en/&quot;&gt;Ruby&lt;/a&gt; interpreter initiated by &lt;a href=&quot;http://blog.fallingsnow.net/&quot;&gt;Evan Phoenix&lt;/a&gt; who has recently been hired by &lt;a href=&quot;http://engineyard.com/&quot;&gt;Engine Yard&lt;/a&gt;.  Engine Yard is a hosting company that is positioning itself as the hosting provider of choice for Ruby applications by a variety of developer focused strategies.  In an effort to raise their profile and gain credibility in the Ruby community they&#8217;ve hired Evan to work full-time on the development of Rubinius.  They&#8217;ve also hired the excellent &lt;a href=&quot;http://brainspl.at/&quot;&gt;Ezra Zygmuntowicz&lt;/a&gt; of camping fame which gives them huge cred in the developer community.  Not only are they just latching onto established efforts, they are creating new markets by going after the shared hosting crew by developing &lt;a href=&quot;http://brainspl.at/articles/2008/02/12/what-do-you-want-to-see-in-mod_rubinius&quot;&gt;mod_rubinius&lt;/a&gt; .   I would guess that the benefits are twofold &#8211; they look like nice guys by giving back to the community, but they also create a very easy path for them to upsell shared hosting into &lt;span class=&quot;caps&quot;&gt;VPS&lt;/span&gt;.  Everyone wins when this kind of effort is put into a business model.&lt;/p&gt;


	&lt;p&gt;Evan and Eric Hodel are out in Australia for the Rubinius Sprint set up by &lt;a href=&quot;http://redartisan.com/blog&quot;&gt;Marcus Crafter&lt;/a&gt; and fellow Engine Yarder &lt;a href=&quot;http://dylanegan.com/&quot;&gt;Dylan Egan&lt;/a&gt; .  In a side trip Evan came to Melbourne and spent three hours explaining how Rubinius worked and answering a heap of really interesting technical questions from the &lt;a href=&quot;http://groups.google.com/group/rails-oceania&quot;&gt;Melbourne crew&lt;/a&gt; before heading out for a few quiet (5am) drinks.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://stateofflux.com/">
    <author>
      <name>mark</name>
    </author>
    <id>tag:stateofflux.com,2008-03-21:17</id>
    <published>2008-03-21T12:18:00Z</published>
    <updated>2008-03-21T12:19:01Z</updated>
    <category term="barcamp"/>
    <category term="barcampmelbourne2008"/>
    <category term="sitepoint"/>
    <link href="http://stateofflux.com/2008/3/21/barcamp-melbourne-2008" rel="alternate" type="text/html"/>
    <title>BarCamp Melbourne 2008</title>
<content type="html">
            &lt;p&gt;&lt;em&gt;I&#8217;ve been a bit absent with my blogging so I&#8217;ve got a few retrospective entries for you.&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://barcampmelbourne.org/&quot;&gt;BarCamp Melbourne&lt;/a&gt; : 60 people, 25 talks and an amazing day of interdisciplinary cahoots unorganized by &lt;a href=&quot;http://benbalbo.com/2008/03/06/barcampmelbourne2008-was-a-huge-success/trackback/&quot;&gt;Ben Balbo&lt;/a&gt; !  What I loved about BarCamp:http://barcamp.org/ was the range of presentations &#8211; everything from programming, databases and information modelling through to media centers, industrial relations, social activities and a hell of a lot of fun.&lt;/p&gt;


	&lt;p&gt;I&#8217;d like to give special mention to &lt;a href=&quot;http://pjf.id.au/&quot;&gt;Paul Fenwick&#8217;s&lt;/a&gt; hilarious and poignant talk on &#8220;An Illustrated History of Failure&#8221;.  He managed to show why testing costs &#8211; and quantified it.  It was a showcase of brilliant execution on a topic which would, with an average presenter, make you groan.&lt;/p&gt;


	&lt;p&gt;Other outstanding talks where Andy G&#8217;s &#8220;OpenLazlo &lt;span class=&quot;caps&quot;&gt;GUI&lt;/span&gt;, jiggy itouch &lt;span class=&quot;caps&quot;&gt;GUI&lt;/span&gt;, openmaji&#8221; and Brent Snook&#8217;s &#8220;Lowering Usability Hurdles with the Wii&#8221;.  Very, very cool stuff.  In reality all the talks were excellent and had a lot to offer.  I can&#8217;t wait to see the what the next BarCamp has to offer.&lt;/p&gt;


	&lt;p&gt;I was lucky enough to win a copy of &lt;a href=&quot;http://&quot;&gt;The &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; Anthology&lt;/a&gt; from SitePoint:http://sitepoint.com/ for my talk on &lt;a href=&quot;http://www.stateofflux.com/assets/2007/7/8/MRUG_-_Monkey_Patching.pdf&quot;&gt;Monkey Patching&lt;/a&gt; (which I&#8217;d given previously as the Ruby Nuby night a few months ago).  The after event drinks were in North Melbourne, with the suds provided by Microsoft&lt;/p&gt;


	&lt;p&gt;You can keep up with the activities on by checking out the &lt;a href=&quot;http://del.icio.us/search/?fr=del_icio_us&amp;amp;#38;p=barcampmelbourne2008&amp;amp;#38;type=all&quot;&gt;BarCampMelbourne2008&lt;/a&gt; tag on &lt;a href=&quot;http://flickr.com/photos/tags/BarCampMelbourne2008&quot;&gt;da&lt;/a&gt; &lt;a href=&quot;http://technorati.com/search/BarCampMelbourne2008?authority=a4&amp;amp;#38;language=en&quot;&gt;internets&lt;/a&gt; .&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://stateofflux.com/">
    <author>
      <name>mark</name>
    </author>
    <id>tag:stateofflux.com,2007-10-03:16</id>
    <published>2007-10-03T14:19:00Z</published>
    <updated>2008-04-02T14:52:04Z</updated>
    <category term="agile"/>
    <category term="markmansour"/>
    <category term="people"/>
    <category term="process"/>
    <category term="shipit"/>
    <category term="tools"/>
    <category term="wds07"/>
    <link href="http://stateofflux.com/2007/10/3/building-a-site-for-people-with-big-imaginations" rel="alternate" type="text/html"/>
    <title>Building a site for people with big imaginations</title>
<content type="html">
            &lt;div&gt;
On Friday I presented a talk at &lt;a href=&quot;http://webdirections.org&quot;&gt;Web Directions South&lt;/a&gt; conveying my tips on how to build a successful web application.  I've embedded the presentation below
&lt;/div&gt;
&lt;div&gt;
&amp;lt;object height=&quot;348&quot; width=&quot;425&quot;&gt;&amp;lt;param /&gt;&amp;lt;/object&gt;
&lt;/div&gt;
&lt;div&gt;
I set up the talk by presenting the issues that come with web development, which are usually new product development issues.  Basically you don't know what you are building until you build it, so embrace the unknown and plan for it.  Even in a sea of change there are things that help you get to market, these include:

&lt;li&gt;
&lt;ol&gt;Good People - look for proactive people who communicate well&lt;/ol&gt;
&lt;ol&gt;Good Tools - there are lots of great tools that help get things done quickly and cheaply, so use them&lt;/ol&gt;
&lt;ol&gt;Simple Development process - use an agile methodology, they are well thought out but hard to get right&lt;/ol&gt;
&lt;ol&gt;Ship it - if you don't ship code, you don't have a product&lt;/ol&gt;
&lt;ol&gt;Fun - make work fun if you want keep your people and get the most out of them (and you!)&lt;/ol&gt;
&lt;/li&gt;
&lt;/div&gt;
&lt;div&gt;
A pretty simple premise really, but it amazing me how easy it is to get this wrong.  Usually I see companies get good people and then give them good tools and build a really overweight process around them so it is impossible to push software out of the organization.  It's a hard problem and this is why successful web apps (and software in general) actually comes about.
&lt;/div&gt;
&lt;div&gt;
If you did see my talk then please leave a comment, I'd love to hear what you thought of it.  But if you didn't I'm also interested in your thoughts on my uploaded presentation.
&lt;/div&gt;
&lt;div&gt;
If anyone has any photos of my presentation I'd love to get a copy - it appears that the official photographer was in the other room during my talk.
&lt;/div&gt;
&lt;em&gt;I've deleted a boatload of comment spam, so if I've deleted a 'real' comment, please let me know and I'll add it back in.&lt;/em&gt;
          </content>  </entry>
  <entry xml:base="http://stateofflux.com/">
    <author>
      <name>mark</name>
    </author>
    <id>tag:stateofflux.com,2007-09-26:14</id>
    <published>2007-09-26T08:20:00Z</published>
    <updated>2007-09-26T08:22:00Z</updated>
    <category term="wds07 presentation webapp sydney"/>
    <link href="http://stateofflux.com/2007/9/26/let-the-webdirections-begin" rel="alternate" type="text/html"/>
    <title>Let the WebDirections begin...</title>
<content type="html">
            &lt;p&gt;I&#8217;m pumped.  I&#8217;ve just arrived in Sydney from my one hour flight from Melbourne.  I&#8217;ve checked in and hooked up to my $30 per day internet connection and I&#8217;m putting the finishing touches on &lt;a href=&quot;http://www.webdirections.org/program/sessions/#mansour&quot;&gt;my presentation&lt;/a&gt;.  I haven&#8217;t spent much time in Sydney but from what I can see it is a beautiful place.  Tonight there is an &lt;a href=&quot;http://www.webindustry.asn.au/events/2007/08/nsw-port80-meetup/&quot; title=&quot;Australian Web Industry Association&quot;&gt;industry meet and greet&lt;/a&gt; which I look forward to downing a few brews and meeting the locals.  Sounds awesome.&lt;/p&gt;


	&lt;p&gt;During the process of writing my talk it has occured to me how much there is to writing software.  My talk is targeted at Web Applications, but when all said and done, the same disciplines are required for web work as they are for all other application development.  I was going to talk about RedBubble and why it was cool, but it was just a bit too specific &#8211; there wasn&#8217;t going to be anything concrete to take away.  I concluded that a more valuable approach would be to convey (in a compressed timeframe) the a collectin of practices that make a group successful.  I assume that the hard skills (HTML, &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;, coding, design) are being worked on because they are the most obvious, but the softer skill and the management practices are the skills that are harder to learn.  So, in 50 minutes, I&#8217;m going to spew forth a collection of good practices with examples with a compresensive set of references.  My hope is that I pique some interest and that the motived ones in the audience will pick up the battern and Go, Go, Go!&lt;/p&gt;


	&lt;p&gt;If you are at Web Directions please come up and say hello and tell me that you&#8217;re reading my blog!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://stateofflux.com/">
    <author>
      <name>mark</name>
    </author>
    <id>tag:stateofflux.com,2007-08-17:11</id>
    <published>2007-08-17T01:19:00Z</published>
    <updated>2007-08-24T05:41:00Z</updated>
    <category term="exception_notification rails agile team"/>
    <link href="http://stateofflux.com/2007/8/17/exceptional-cow" rel="alternate" type="text/html"/>
    <title>Exceptional Cow!</title>
<content type="html">
            &lt;p&gt;Surprisingly, &lt;a href=&quot;http://www.redbubble.com/&quot;&gt;we&lt;/a&gt; are not perfect.  Shocking.  Even after our testing, we sometime release code into production with errors.  We try to be good boys by not just ignoring these errors but we get the system to log them and send the info to our tech mailing list.  In the Rails world, the excellent &lt;a href=&quot;http://svn.rubyonrails.org/rails/plugings/exeption_notification/&quot;&gt;Exception Notifier&lt;/a&gt; plugin, from the prolific Jamis Buck, makes this a breeze.  If you&#8217;ve got a Rails project and your not using it, then you should.  Go on, get it!&lt;/p&gt;


	&lt;p&gt;But now what?  You&#8217;ve got the emails but with the constant pressure to get things done it becomes easy for everyone to just think &#8220;Oh, I&#8217;m a bit busy, I&#8217;ll let one of the other guys do it.&#8221;  But they don&#8217;t, because we&#8217;re all busy.  Introducing, the Exceptional Cow!&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://farm2.static.flickr.com/1066/634790579_13935a44ef_m.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;The Exceptional Cow (a &lt;a href=&quot;http://www.tucows.com/&quot;&gt;Tucows&lt;/a&gt; squigy toy)&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;At our end of iteration review, like all good agile shops, we go through what&#8217;s good, what could be done better, what still puzzles us and what we are going to do next time (but details on this are for another post).  We also have The Exceptional Cow™.&lt;/p&gt;


	&lt;p&gt;Whoever has the cow is responsible for triaging all incoming exceptions for that iteration.  At the end of each iteration The Exceptional Cow is ceremoniously passed to the next bovine herder.  As the cow herder, you have the responsibility of examining all incoming exceptions and fixing it if it is a no brainer or writing it up as a bug for someone else to fix if you don&#8217;t have the time or if someone else has a much better grasp on the issue.  Quite often all exceptions for the week are attacked in the final hours before we close off the iteration as we don&#8217;t want to start new functionality at that point.&lt;/p&gt;


	&lt;p&gt;What it has done for RedbBubble is make our code more robust which means our customers have a better experience.  It also makes everyone just a bit more careful and tolerant of exceptions.  It is also a great way to get everyone across parts of the code base they wouldn&#8217;t normally look at including the systems side of things.  The cow is our friend&#8230;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Edit&lt;/strong&gt;: The &lt;a href=&quot;http://about.tucows.com/2007/08/21/the-exceptional-squishy-cow/&quot;&gt;Tucows developer blog&lt;/a&gt; picked up on my post &#8211; Thanks!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://stateofflux.com/">
    <author>
      <name>mark</name>
    </author>
    <id>tag:stateofflux.com,2007-07-08:10</id>
    <published>2007-07-08T11:55:00Z</published>
    <updated>2007-07-08T12:11:12Z</updated>
    <category term="ruby usergroup ducktyping monkeypatch openclasses slides nuby"/>
    <link href="http://stateofflux.com/2007/7/8/nuby-night" rel="alternate" type="text/html"/>
    <title>A full house at Melbourne Ruby Newbie Night</title>
<content type="html">
            &lt;p&gt;The Melbourne Ruby User&#8217;s Group held it&#8217;s first ever Nuby night last week.  It was somewhat inspired by the RailsConf 2007 RejectConf that &lt;a href=&quot;http://crafterm.net/blog&quot;&gt;Marcus Crafter&lt;/a&gt; and I attended earlier in the year with the idea of many short talks presented by many speakings being preferred over a few &#8216;experts&#8217; presenting on a wider range of issues.  It also acted like a gong show &#8211; you had a hard limit of 5 minutes and when the gong went off you could imagine a walking stick wrapped around your neck pulling you off the stage.  No pressure&#8230; Really&#8230;&lt;/p&gt;


	&lt;p&gt;I spoke about the animals of the Ruby world &#8211; monkey patching and duck typing.  After researching my talk I realized that I only had a cursory knowledge of both topics but preparing for this talk gave me the reason to learn more.  I enjoyed the experience and would highly recommend it to anyone who wants to practice their presentation skills.&lt;/p&gt;


	&lt;p&gt;A big thank you to &lt;a href=&quot;http://notahat.com&quot;&gt;Pete Yandell&lt;/a&gt; for continuing to organize the &lt;a href=&quot;http://groups.google.com/group/melbourne-ruby&quot;&gt;Melbourne Ruby&lt;/a&gt; community and to &lt;a href=&quot;http://www.cogentconsulting.com.au/screencasts/&quot;&gt;Marty Andrews&lt;/a&gt; for recording and editing the presentations.&lt;/p&gt;


You can download my talks
	&lt;ul&gt;
	&lt;li&gt;Monkey Patching (Open Classes) &#8211; &lt;a href=&quot;http://www.stateofflux.com/assets/2007/7/8/MRUG_-_Monkey_Patching.pdf&quot;&gt;slides&lt;/a&gt; and &lt;a href=&quot;http://www.cogentconsulting.com.au/screencasts/rubynuby/markmansour-monkey-patching.mov&quot;&gt;movie&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Duck Typing &#8211; &lt;a href=&quot;http://www.stateofflux.com/assets/2007/7/8/MRUG_-_duck_typing.pdf&quot;&gt;slides&lt;/a&gt; and &lt;a href=&quot;http://www.cogentconsulting.com.au/screencasts/rubynuby/markmansour-duck-typing.mov&quot;&gt;movie&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://www.flickr.com/photos/71993871@N00/sets/72157600656732623/&quot;&gt;Photos of the night&lt;/a&gt; too&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Big props to &lt;a href=&quot;http://justinfrench.com/&quot;&gt;Justin French&lt;/a&gt; also from RedBubble who presented and to &lt;a href=&quot;http://rhnh.net/&quot;&gt;Xavier Shay&lt;/a&gt; who didn&#8217;t present due to time constraints.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://stateofflux.com/">
    <author>
      <name>mark</name>
    </author>
    <id>tag:stateofflux.com,2007-06-17:5</id>
    <published>2007-06-17T12:01:00Z</published>
    <updated>2008-04-02T15:05:08Z</updated>
    <category term="find"/>
    <category term="grep"/>
    <category term="rails"/>
    <link href="http://stateofflux.com/2007/6/17/a-fast-grep-for-rails" rel="alternate" type="text/html"/>
    <title>A fast grep for Rails</title>
<content type="html">
            &lt;p&gt;I often want to grep for a word recursively within a directory.  That is easy!  But quite often I know there are a bunch of directories that I can ignore.  For instance, in my rails apps I don&#8217;t want to hear about subversion directories and I don&#8217;t want to search the vendor tree.&lt;/p&gt;


	&lt;p&gt;I also don&#8217;t want to look at files that are really big &#8211; they are usually log files or binaries of some sort that I just don&#8217;t care about.  So I put together the monster find and grep string that works for me.&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;find . -path '*/.svn' -prune \&lt;tt&gt;
&lt;/tt&gt;    -o -path '*/vendor' -prune \&lt;tt&gt;
&lt;/tt&gt;    -o -path '*/log' -o -path '*~' -prune \&lt;tt&gt;
&lt;/tt&gt;    -o \( -size -100000c -type f \) \&lt;tt&gt;
&lt;/tt&gt;    -print0 | xargs -0 grep -ne &amp;quot;SEARCH&amp;quot;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Let&#8217;s break it down.&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;find .&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
 &#8211; start searching for files recurively, starting from the current directory
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;-path '*/.svn' -prune&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
 &#8211; ignore .svn directories
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;-o -path '*/vendor'&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
 &#8211; OR ignore the vendor directory too.
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;-o -path '*~'&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
 &#8211; OR ignore all the emacs backup files
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;-o -path '*/log' -prune&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
 &#8211; ignore the log directory
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;-o \( -size -100000c -type f \)&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
 &#8211; OR make sure the size is less than 100,000 characters and the type of thing is a file (not a pipe or a director or socket) &#8211; this usually gets rid of all non source files
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;-print0&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
 &#8211; tells find to terminate the line with a 0.  Which sounds really dull, but you can&#8217;t pipe the data (get the output from &#8216;find&#8217; to &#8216;grep&#8217;) if there is a space in the filename.
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;|&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
 &#8211; push the data from the command on the left to the command on the right
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;xargs -0&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
 &#8211; take the input from the fine command, terminated with a 0 (the print0 from find) and send it to grep.
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;grep -ne&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
 &#8211; search each file with a regular expression and when a match is found print the line number with the filename.

	&lt;p&gt;The easiest way to use this is to put it into a shell file &#8211; I&#8217;ve put it into s.sh.&lt;/p&gt;


	&lt;p&gt;My s.sh file looks like this&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;#!/bin/sh&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;if  [ ${#1} -gt 0  ]&lt;tt&gt;
&lt;/tt&gt;then&lt;tt&gt;
&lt;/tt&gt;    find . -path '*/.svn' -prune -o -path '*/vendor' -prune -o -path '*/log' -o -path '*~' -prune -o \( -size -100000c -type f \) -print0 | xargs -0 grep -ne  $1&lt;tt&gt;
&lt;/tt&gt;else&lt;tt&gt;
&lt;/tt&gt;    echo &amp;quot;Not enough parameters.  Usage: ./$0 searchstring&amp;quot;&lt;tt&gt;
&lt;/tt&gt;fi&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Then I make it executable by&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;chmod 755 s.sh&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;If you want to find all of the before filters you would do this&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;s.sh &amp;quot;before_filter&amp;quot;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;and enjoy you super fast find command.&lt;/p&gt;
          </content>  </entry>
</feed>
