<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Educate. Liberate. &#187; snippets</title>
	<atom:link href="http://www.nullstyle.com/category/snippets/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.nullstyle.com</link>
	<description></description>
	<lastBuildDate>Mon, 10 Nov 2008 05:33:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>link_to as a block helper</title>
		<link>http://www.nullstyle.com/2007/06/19/link_to-as-a-block-helper/</link>
		<comments>http://www.nullstyle.com/2007/06/19/link_to-as-a-block-helper/#comments</comments>
		<pubDate>Tue, 19 Jun 2007 17:43:22 +0000</pubDate>
		<dc:creator>nullstyle</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://nullstyle.com/2007/06/19/link_to-as-a-block-helper/</guid>
		<description><![CDATA[When it comes to creating helpers for the view portion of satisfaction, I&#8217;ve started taking the approach that once I see something &#8220;ugly&#8221; twice in the rhtml that it should be extracted out into a helper. In many cases, before that. Today&#8217;s wart? link_to calls that have html for the text content. take for example: [...]]]></description>
			<content:encoded><![CDATA[<p>When it comes to creating helpers for the view portion of satisfaction, I&#8217;ve started taking the approach that once I see something &#8220;ugly&#8221; twice in the rhtml that it should be extracted out into a helper.  In many cases, before that.</p>

<p>Today&#8217;s wart?  <code>link_to</code> calls that have html for the text content.  take for example:</p>

<pre class="sh_html">
&lt;%= link_to "&lt;strong&gt;#{product.name}&lt;/strong&gt;&lt;span&gt;#{pluralize(product.topic_count(company), 'topic')}&lt;/span&gt;", href, :class =&gt; "product_label" %&gt;
</pre>

<p>ewww&#8230;  and that doesn&#8217;t even get into having href defined above in a &lt;%  %> block.  So, I extended <code>link_to</code> with the help of <code>alias_method_chain</code> such that it will take a block argument instead of the its normal first parameter.</p>

<pre class="sh_html">
&lt;% link_to browse_url(product), :class =&gt; "product_label" do %&gt;
  &lt;strong&gt;&lt;%= product.name %&gt;&lt;/strong&gt;
  &lt;span&gt;(&lt;%= pluralize(product.topic_count(company), 'topic') %&gt;)&lt;/span&gt;
&lt;% end %&gt;
</pre>

<p>Much more readable.  See the code <a href="http://nullstyle.com/wp-content/uploads/2007/09/block-link-to.rb" title="block_link_to.rb">block_link_to.rb</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.nullstyle.com/2007/06/19/link_to-as-a-block-helper/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>15 minute hack:  Poor man&#8217;s function composition</title>
		<link>http://www.nullstyle.com/2007/06/14/15-minute-hack-poor-mans-function-composition/</link>
		<comments>http://www.nullstyle.com/2007/06/14/15-minute-hack-poor-mans-function-composition/#comments</comments>
		<pubDate>Thu, 14 Jun 2007 17:38:55 +0000</pubDate>
		<dc:creator>nullstyle</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://nullstyle.com/2007/06/13/15-minute-hack-poor-mans-function-composition/</guid>
		<description><![CDATA[I loves me some functional programming and I loves me some Symbol#to_proc (which lets you do .each(&#38;:upcase)). One of those _fp_ features I wish I had in ruby-land was function composition. Specifically, I find myself writing things like: initials = ["Foo". "Bar", "Baz"].map{&#124;str&#124; str.first.upcase} That is fine, but just isn&#8217;t as cool as leveraging to_proc [...]]]></description>
			<content:encoded><![CDATA[<p>I loves me some functional programming and I loves me some <a href="http://pragdave.pragprog.com/pragdave/2005/11/symbolto_proc.html"><code>Symbol#to_proc</code></a> (which lets you do <code>.each(&amp;:upcase)</code>).</p>

<p>One of those _fp_ features I wish I had in ruby-land was function composition.  Specifically, I find myself writing things like:</p>

<pre class="sh_ruby">initials = ["Foo". "Bar", "Baz"].map{|str| str.first.upcase}</pre>

<p>That is fine, but just isn&#8217;t as cool as leveraging <code>to_proc</code> in some fashion.  In the more &#8220;stupid, stupid, stupid&#8221; case, i&#8217;ve also seen things like:</p>

<pre class="sh_ruby">initials = ["Foo". "Bar", "Baz"].map(&#038;:first).map(&#038;:upcase)  # Eww, unnecessary iterations...</pre>

<p>Anways, Ruby does have function composition ([<code>Proc#compose</code>][2]), thanks to the Ruby facets project, but working directly with lambdas isn&#8217;t nearly as friendly as I desire.  So, I spent 15 minutes to hack together a means that I like.  Here&#8217;s what it looks like:</p>

<pre class="sh_ruby">["foo", "bar", "baz"].map(&#038;:first >> :upcase)</pre>

<p>Which reads, map, using :first <em>then</em> :upcase.  <code>&gt;&gt;</code> is left associative, like <code>"foo".first.upcase</code>, opposite of Haskell composition where <code>foobar = foo . bar</code>  reads foo <em>follows</em> bar.</p>

<p>Also, the snippet linked below lets you do something like:</p>

<pre class="sh_ruby">
  class String
    compose(:initial, &#038;:first >> :upcase)
  end
  "foo".initial   # => "F"
</pre>

<p>Now a re-implementation of ActiveSupport&#8217;s Module#delegate:</p>

<pre class="sh_ruby">
class Module
  def delegate(*methods)
    options = methods.pop
    unless options.is_a?(Hash) &#038;&#038; to = options[:to]
      raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter)."
    end

    methods.each do |method|
      compose(method, &#038;to >> method)
    end
  end
end
</pre>

<p>Perhaps not necessary, but I found it interesting and fun to write.  Thoughts?</p>

<p><a href="http://nullstyle.com/wp-content/uploads/2007/09/compose.rb" title="compose.rb">compose.rb</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.nullstyle.com/2007/06/14/15-minute-hack-poor-mans-function-composition/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Caching time_ago_in_words</title>
		<link>http://www.nullstyle.com/2007/06/02/caching-time_ago_in_words/</link>
		<comments>http://www.nullstyle.com/2007/06/02/caching-time_ago_in_words/#comments</comments>
		<pubDate>Sat, 02 Jun 2007 17:35:50 +0000</pubDate>
		<dc:creator>nullstyle</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://nullstyle.com/2007/06/02/caching-time_ago_in_words/</guid>
		<description><![CDATA[I&#8217;m a big fan of the &#8220;english&#8221; timestamps that so often get used in apps these days; &#8220;Sat Jun 02 17:55:56 -0700 2007&#8243; means almost nothing to me without active thought. It is much nicer to read &#8220;about a minute ago&#8221;, it requires no processing on my part. As many of you know, rails bundles [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a big fan of the &#8220;english&#8221; timestamps that so often get used in apps these days; &#8220;Sat Jun 02 17:55:56 -0700 2007&#8243; means almost nothing to me without active thought.  It is much nicer to read &#8220;about a minute ago&#8221;, it requires no processing on my part.  As many of you know, rails bundles this functionality into a helper called <code>time_ago_in_words</code>, and it works wonderfully.  </p>

<p>The only issue is that you can&#8217;t page cache these timestamps.  If you do, &#8220;one minute ago&#8221; won&#8217;t be right in short order.  So, I worked up a little remix for <code>time_ago_in_words</code> that solves this problem.</p>

<p>The secret sauce is Javascript, as usual. <code>cacheable_time_ago_in_words</code> outputs a javascript call that does the translation:</p>

<pre class="sh_ruby">
  module CachedDateHelper
    def cachable_time_ago_in_words(from)
      js_call = javascript_tag "document.write(time_ago_in_words(#{(from.to_i * 1000).to_json}) + ' ago');"
      <<-EOS
        #{js_call}
        <noscript>on #{from.to_formatted_s(:long)}</noscript>
      EOS
    end
  end
</pre>

<p>And then, on the javascript side:</p>

<pre class="sh_javascript">
  function time_ago_in_words(from) {
   return distance_of_time_in_words(new Date().getTime(), from)
  }

  function distance_of_time_in_words(to, from) {
    seconds_ago = ((to  - from) / 1000);
    minutes_ago = Math.floor(seconds_ago / 60)

    if(minutes_ago == 0) { return "less than a minute";}
    if(minutes_ago == 1) { return "a minute";}
    if(minutes_ago < 45) { return minutes_ago + " minutes";}
    if(minutes_ago < 90) { return " about 1 hour";}
    hours_ago  = Math.round(minutes_ago / 60);
    if(minutes_ago < 1440) { return "about " + hours_ago + " hours";}
    if(minutes_ago < 2880) { return "1 day";}
    days_ago  = Math.round(minutes_ago / 1440);
    if(minutes_ago < 43200) { return days_ago + " days";}
    if(minutes_ago < 86400) { return "about 1 month";}
    months_ago  = Math.round(minutes_ago / 43200);
    if(minutes_ago < 525960) { return months_ago + " months";}
    if(minutes_ago < 1051920) { return "about 1 year";}
    years_ago  = Math.round(minutes_ago / 525960);
    return "over " + years_ago + " years"
  }
</pre>

<p>You'll notice there is no support for the rails-like <code>include_seconds</code> option.  That is left as an exercise for the reader (ie.  I don't need to use it).  Using this helper will let you page cache your views, greatly improving performance. It even has a fallback to absolute timestamps for those out there with a javascript disability.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nullstyle.com/2007/06/02/caching-time_ago_in_words/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
