<?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>MarkMcB</title>
	<atom:link href="http://markmcb.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://markmcb.com</link>
	<description>Mark McBride of San Francisco</description>
	<lastBuildDate>Sun, 15 Apr 2012 01:13:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Replacing â€“, â€™, â€œ, etc., with UTF-8 Characters in Ruby on Rails</title>
		<link>http://markmcb.com/2011/11/07/replacing-ae%e2%80%9c-ae%e2%84%a2-aeoe-etc-with-utf-8-characters-in-ruby-on-rails/</link>
		<comments>http://markmcb.com/2011/11/07/replacing-ae%e2%80%9c-ae%e2%84%a2-aeoe-etc-with-utf-8-characters-in-ruby-on-rails/#comments</comments>
		<pubDate>Mon, 07 Nov 2011 17:34:49 +0000</pubDate>
		<dc:creator>markmcb</dc:creator>
				<category><![CDATA[Server Administration]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[characters]]></category>
		<category><![CDATA[encoding]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[utf8]]></category>

		<guid isPermaLink="false">http://markmcb.com/?p=449</guid>
		<description><![CDATA[Recently I upgraded some older Rails applications to Rails 3.1 and Ruby 1.9.2 (from 2.3 and 1.8.7 respectively). One post-upgrade issue was that text content had a lot of garbage showing up like â€“, â€™, â€œ, etc. For example, here&#8217;s &#8230; <a href="http://markmcb.com/2011/11/07/replacing-ae%e2%80%9c-ae%e2%84%a2-aeoe-etc-with-utf-8-characters-in-ruby-on-rails/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Recently I upgraded some older Rails applications to Rails 3.1 and Ruby 1.9.2 (from 2.3 and 1.8.7 respectively).  One post-upgrade issue was that text content had a lot of garbage showing up like â€“, â€™, â€œ, etc.  For example, here&#8217;s an actual example from a comment in one of the applications:</p>
<blockquote><p>One of my â€œthings to do before Iâ€™m 50â€ is</p></blockquote>
<p>This should read:</p>
<blockquote><p>One of my “things to do before I’m 50” is </p></blockquote>
<p>It turns out these are just special characters that were improperly encoded for utf-8.  The fix is simple enough: loop through your content and replace where needed.  </p>
<p>If your database is big, this could take a long time unless you disable callbacks.  The script below highlights both how to replace the characters using Ruby and how to disable your Rails callbacks to make this script run in seconds instead of hours (depending on the complexity of your callbacks).</p>
<pre class="brush:ruby">
replacements = []
replacements << ['â€¦', '…']           # elipsis
replacements << ['â€“', '–']           # long hyphen
replacements << ['â€™', '’']           # curly apostrophe
replacements << ['â€œ', '“']           # curly open quote
replacements << [/â€[[:cntrl:]]/, '”'] # curly close quote
klasses = [Comment, Article]           # replace with relevant classes

klasses.each do |klass|
  klass.all.each do |obj|
    original = obj.body
    replacements.each{ |set| obj.body = obj.body.gsub(set[0], set[1]) }
    unless (original == obj.body)
      #### Remove or Customize ####
      # This should reflect your models' callbacks.  It should be safe
      # since we're just doing a simple find/replace.
      Comment.skip_callback(:save, :after,  :do_after_save_tasks ) if obj.is_a?(Comment)
      Article.skip_callback(:save, :before, :do_before_save_tasks) if obj.is_a?(Article)
      #### End Remove or Customize ####
      obj.save!
    end
  end
end
</pre>
<p>If you noticed, I used a regular expression for the curly close quote.  This is because there is an invisible control character that is not easily copy/pasted into your code.  Using <code>[[:cntrl:]]</code> is just an easier way to catch it.</p>
]]></content:encoded>
			<wfw:commentRss>http://markmcb.com/2011/11/07/replacing-ae%e2%80%9c-ae%e2%84%a2-aeoe-etc-with-utf-8-characters-in-ruby-on-rails/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Integer Compression in Ruby (Base-10 to Base-62)</title>
		<link>http://markmcb.com/2011/11/02/integer-compression-in-ruby-base-10-to-base-62/</link>
		<comments>http://markmcb.com/2011/11/02/integer-compression-in-ruby-base-10-to-base-62/#comments</comments>
		<pubDate>Wed, 02 Nov 2011 21:17:06 +0000</pubDate>
		<dc:creator>markmcb</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[integer]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://markmcb.com/?p=415</guid>
		<description><![CDATA[A few days ago I was thinking about all those link shortening sites and wondered how easy it would be to compress a base-10 number like 1,234,567,890 to something much smaller like 1LY7VK. Here&#8217;s what I came up with: class &#8230; <a href="http://markmcb.com/2011/11/02/integer-compression-in-ruby-base-10-to-base-62/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A few days ago I was thinking about all those link shortening sites and wondered how easy it would be to compress a base-10 number like 1,234,567,890 to something much smaller like 1LY7VK.  Here&#8217;s what I came up with:</p>
<pre class="brush:ruby">class IntegerCompressor

  CompressionCharacterSet = %w(0 1 2 3 4 5 6 7 8 9
  A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
  a b c d e f g h i j k l m n o p q r s t u v w x y z)

  def self.to_base
    CompressionCharacterSet.length
  end

  def self.compress(number_to_convert)
    digits_needed = Math.log(number_to_convert, IntegerCompressor.to_base).floor + 1
    compressed_number_string = ''
    previous_remainder = number_to_convert
    (digits_needed-1).downto(0) do |power|
      r=previous_remainder.divmod(IntegerCompressor.to_base**power)
      compressed_number_string << CompressionCharacterSet[r[0]]
      previous_remainder = r[1]
    end
    compressed_number_string
  end

  def self.decompress(compressed_number)
    power = 0
    base_10_integer = 0
    compressed_number.to_s.reverse.each_char do |digit|
      base_10_integer += ((IntegerCompressor.to_base**power)*CompressionCharacterSet.index(digit))
      power+=1
    end
    base_10_integer
  end

end
</pre>
<p>It seems to work:</p>
<pre class="brush:ruby">$ irb
>> require '/path/to/file/integer_compressor.rb'
=> true
>> IntegerCompressor.compress 1234567890
=> "1LY7VK"
>> IntegerCompressor.decompress "1LY7VK"
=> 1234567890
</pre>
<p>If anyone has a more elegant solution, I'd be curious to see it.</p>
<p>(Thanks to <a href="https://plus.google.com/u/0/110560946703452708530/posts">Tamara</a> for the log refresher.)</p>
]]></content:encoded>
			<wfw:commentRss>http://markmcb.com/2011/11/02/integer-compression-in-ruby-base-10-to-base-62/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>3 Reasons Aperture and Picasa are a Great Photo Combo</title>
		<link>http://markmcb.com/2011/10/28/3-reasons-aperture-and-picasa-are-a-great-photo-combo/</link>
		<comments>http://markmcb.com/2011/10/28/3-reasons-aperture-and-picasa-are-a-great-photo-combo/#comments</comments>
		<pubDate>Fri, 28 Oct 2011 13:41:15 +0000</pubDate>
		<dc:creator>markmcb</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[aperture]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[lightroom]]></category>
		<category><![CDATA[photography]]></category>
		<category><![CDATA[photos]]></category>
		<category><![CDATA[picasa]]></category>
		<category><![CDATA[sharing]]></category>
		<category><![CDATA[social]]></category>
		<category><![CDATA[web services]]></category>

		<guid isPermaLink="false">http://markmcb.com/?p=418</guid>
		<description><![CDATA[I spent the evening hours of many days in October looking for a photo management and sharing solution.&#160; I tried a lot of software, workflows, web applications, mobile apps, etc.&#160; It was tedious and a little frustrating.&#160; I was surprised &#8230; <a href="http://markmcb.com/2011/10/28/3-reasons-aperture-and-picasa-are-a-great-photo-combo/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I spent the evening hours of many days in October looking for a photo management and sharing solution.&nbsp; I tried a lot of software, workflows, web applications, mobile apps, etc.&nbsp; It was tedious and a little frustrating.&nbsp; I was surprised at how incomplete most of the options were.&nbsp; I had hoped for a one-app-does-it-all solution, but after a great deal of exploring, I&#8217;m quite happy with the Aperture + Picasa combination to meet my photo storing and sharing needs.</p>
<h2>My Needs</h2>
<p>Before I get into why I picked Aperture and Picasa, let me explain my specific needs:</p>
<ul>
<li><b>I Need to Manage Professional Grade Photos</b> &#8211; By no measure am I a pro photographer, but I have a nice camera (Canon T2i w/ 18-55mm and 55-250mm lenses).&nbsp; I bought it in January and I&#8217;ve really enjoyed taking high quality photos.&nbsp; I&#8217;m currently shopping around for nicer lenses and possibly a camera upgrade.&nbsp; The bottom line is I have good equipment and it&#8217;s getting better.&nbsp; I take between 100-1000 photos a month with each photo over 10 MB.&nbsp; I&#8217;m a bit of a hoarder when it comes to my photos.&nbsp; Aside from the obvious terrible pictures, I tend to keep them all.&nbsp; I need a management application capable of handling thousands of large photos.<b><br /></b></li>
<li><b>I Want to Share Some Photos with Lots of People</b> &#8211; I&#8217;d like to have a workflow where I put the photos on my computer, review them, pick the ones I want to share, and share them.&nbsp; The faster this process the better.&nbsp; Also, after I post them, I&#8217;d like to be able to make tweaks/edits, add meta data, etc., locally (i.e., without needing an Internet connection) and then at some point have them sync up with little/no effort.&nbsp; I don&#8217;t want the sync to override what others have done online, e.g., tagging, comments, etc., i.e., it should be a true sync rather than a re-upload.</li>
<li><b>I Have an Existing Backup Solution</b> &#8211; I use <a href="http://blog.markmcb.com/2011/07/crashplan-for-large-distributed-cheap.html">Crashplan to backup my computer</a>.&nbsp; It&#8217;s awesome and I highly recommend it.&nbsp; As such, I don&#8217;t need either my management or sharing applications to worry too much about backup.&nbsp; What I do care about is the ability to quickly make local copies, e.g., copy everything to a separate drive.&nbsp; I don&#8217;t consider this backup as it wouldn&#8217;t do me any good if my house burned down, but it&#8217;s good if a library gets corrupted, deleted, etc., simply because it&#8217;s faster.&nbsp; Ultimately, I don&#8217;t need to have 100% of my photos backed up at full quality using the same service with which I share photos (but if it does that, then great!).</li>
</ul>
<p><span id="more-418"></span></p>
<h2>The Reasons</h2>
<p>
There are many attributes of the software and web applications listed below.&nbsp; Each has a strength.&nbsp; I am trying to highlight what I think is the best solution for my needs (above).&nbsp; Yours may vary.&nbsp; By no means am I saying this is the only solution.</p>
<h3>Aperture is Cheaper and Better than the Competition</h3>
<div style="float: right; margin: 0 0 20px 30px"><a href="http://a5.mzstatic.com/us/r1000/100/Purple/f9/c0/fe/mzi.zgglihev.175x175-75.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="http://a5.mzstatic.com/us/r1000/100/Purple/f9/c0/fe/mzi.zgglihev.175x175-75.png" /></a>
<div style="color: #999; font-size: 0.9em; text-align: center">Apple&#8217;s Aperture is <br />
powerful, easy to use,<br /> and cheap!</div>
</div>
<p>
Let me make one point crystal clear: I don&#8217;t do a lot of post-processing on my images.&nbsp; As stated above, I&#8217;m not a pro.&nbsp; I don&#8217;t care if there was a speck in photo 317 of 485.&nbsp; I&#8217;m not worried if the color isn&#8217;t worthy of the cover of the National Geographic magazine.&nbsp; The raw output of my camera is awesome and generally meets my needs as is.&nbsp; As long as I can crop, adjust the brightness, and do some other very minor edits, I don&#8217;t need much power in this area.</p>
<p>What I do a lot though, is organize.&nbsp; I&#8217;m an organizing fiend.&nbsp; The two applications I considered in great detail to aid with organization were <a href="http://www.adobe.com/products/photoshoplightroom/">Adobe&#8217;s Lightroom</a> ($299) and <a href="http://www.apple.com/aperture/">Apple&#8217;s Aperture</a> ($79).&nbsp; Aperture was notably better for my needs for a few key reasons:</p>
<ol>
<li>It&#8217;s $220 cheaper.&nbsp; I&#8217;d rather invest that cash in a camera or lens.</li>
<li>Projects, folders, albums, and smart albums in Aperture.&nbsp; These 4 items give you a great deal of organizing power.&nbsp; For my workflow, I do this:</li>
<ol>
<li>Put a group of photos in a project</li>
<li>Go through the photos adding meta data.&nbsp; Of note, I mark photos &#8220;green&#8221; that I&#8217;m willing to share with the world. (Along with other colors/flags for other meanings.)</li>
<li>I create a subordinate smart album called &#8220;Public&#8221; and have it only show green photos.</li>
<li>I export that album for use with Picasa (see below).</li>
</ol>
<li>Using Aperture is a pleasant xperience.&nbsp; When trying to flip through thousands of photos in Lightroom you&#8217;re forced to use a fairly inflexible view.&nbsp; Photos have giant margins, don&#8217;t resize well, and in general it&#8217;s hard to view things.&nbsp; Aperture on the other hand is dead simple.&nbsp; Looking at your whole library or individual projects is easy and the interface is minimal.&nbsp; This translates to more looking at photos and less looking at Aperture.&nbsp; Perfect!&nbsp; Lightroom in general felt clunky.</li>
<li>Lightroom doesn&#8217;t do geotagging.</li>
<li>Lightroom doesn&#8217;t do faces.</li>
</ol>
<p>There was one point the both were terrible at: syncing with a web service.&nbsp; In my dream world, these apps would allow their organizational features to act as analogs to the organizational features offered by web services.&nbsp; Maybe a project is a &#8220;collection&#8221; in Flickr and a &#8220;web album&#8221; in Picasa.&nbsp; I would be able to tell Aperture, &#8220;always sync my changes&#8221; and the web service would just get updated as I edited. &nbsp; Unfortunately, this doesn&#8217;t exist.&nbsp; What does exist are a handful of clunky and frustrating publishing plugins that seemed really good at not meeting my needs.&nbsp; Aperture&#8217;s built-in Flickr plugin did sync, but in a weird way, e.g., if you decide to stop syncing, you&#8217;re forced to delete objects at Flickr.&nbsp; No good.&nbsp; To be fair, they can only be good as the API of the web service they interface with, but regardless, they don&#8217;t do what I need.</p>
<p>Despite the lack of sync, I now have a highly organized, easy to view and navigate photo management solution with Aperture.&nbsp; Now I just need to get these great photos on the web!</p>
<h3>For Sharing, Picasa&#8217;s Desktop Interface Offers the Most Control</h3>
<p>If you haven&#8217;t looked at all the web solutions out there, let me simplify it for you.&nbsp; The major features are:</p>
<ul>
<li> storage &#8211; $ per GB</li>
<li>transport &#8211; how to get photos to the service</li>
<li>interface &#8211; how users see your photos</li>
<li>manipulation &#8211; what you can do to the photos online</li>
<li>social &#8211; how you share</li>
<li>privacy/ownership &#8211; who sees and your copyrights</li>
<li>community &#8211; how many people are using the service</li>
</ul>
<p>Storage winner: Flickr.&nbsp; For $24/yr, it&#8217;s unlimited storage.&nbsp; So, if you are a pro and are pushing out thousands of pictures a month, it&#8217;d be tough to beat.&nbsp; For $20/yr Google&#8217;s Photo service offers 80 GB.&nbsp; So it&#8217;s close if you&#8217;re not pushing everything.</p>
<p>Transport winner: Google.&nbsp; With their Picasa app, you just tell the app where to look for photos and how you want them to be treated once on Google.&nbsp; Then you just say sync.&nbsp; Changed your mind?&nbsp; Didn&#8217;t tag someone?&nbsp; Want to add a geo location?&nbsp; Just do it in Picasa and it immediately shows up online.&nbsp; You can stop syncing at any time too.&nbsp; It&#8217;s awesome.&nbsp; The only drawback is that you&#8217;ll probably want to export your photos from Aperture to a separate location for Picasa.&nbsp; I just export at a much smaller size (largest dimension 1024px) and don&#8217;t worry about the redundant storage.&nbsp; If you&#8217;re dead set on a single file structure, then Lightroom might be your tool.&nbsp; It will let you manage the file system, which means you can have Picasa and Lightroom accessing the same folders.</p>
<p>Interface winner: They&#8217;re all pretty good, though Flickr is oddly clunky for being such a highly used site.</p>
<p>Manipulation winner: Google.&nbsp; Edit photos in Picasa or on-line.&nbsp; The available editing feature are well beyond my needs.</p>
<p>Social winner: Google.&nbsp; Like manipulation above, how you share photos is super easy: picasa, the web, your phone, etc.&nbsp; The key difference though is Picasa.&nbsp; It makes the sharing process super easy.</p>
<p>Privacy/Ownership winner: Google.&nbsp; You have a great deal of access control.&nbsp; With Flickr you can share with two groups: friends or family (yet another bizarre lack of control from such a big site).&nbsp; Flickr has more copyright choices, but unless you&#8217;re a pro, I don&#8217;t think this really matters too much.</p>
<p>Community winner: They have different niches.&nbsp; Friends: Google, Facebook, Snapjoy.&nbsp; Pros: Flickr, 500px.</p>
<div style="float: right; margin: 0 0 20px 30px; width: 200px; text-align: center"><a href="http://upload.wikimedia.org/wikipedia/en/8/86/Picasa_logo.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="http://upload.wikimedia.org/wikipedia/en/8/86/Picasa_logo.png" /></a>
<div style="color: #999; font-size: 0.9em; text-align: center">Google’s Picasa offers <br />a nice way  to interact <br />with a web service<br /> straight from your desktop.  <br />And it’s free!</div>
</div>
<p>
When I initially started my process for finding an on-line service, I just assumed Flickr would be the best.&nbsp; I had an account that I hadn&#8217;t used much and I decided to bump it up to a pro account.&nbsp; It was disappointing.&nbsp; Aside from the massive storage and established community, there&#8217;s really no good reason to use Flickr from a tool/service standpoint.&nbsp; From what I read Yahoo! doesn&#8217;t see it as all that important to their core business either, so it&#8217;s hard to say if they&#8217;ll ever catch up.</p>
<p>Google was the last service I considered.&nbsp; Once I used Picasa, I was sold.&nbsp; If you&#8217;ve not tried it, check it out.&nbsp; (For reference, I also considered Facebook, Smugmug, Photobucket, Snapjoy, and 500px.)</p>
<p>As a side note, 500px is a pretty awesome place to browse.&nbsp; It didn&#8217;t meet my needs, but is certainly notable.  Check them out.</p>
<h3>Google Offers the Best Integrated Services</h3>
<p></p>
<div style="float: right; margin: 0 0 20px 30px"><a href="http://www.google.com/intl/en_com/images/srpr/logo3w.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="http://www.google.com/intl/en_com/images/srpr/logo3w.png" /></a>
<div style="color: #999; font-size: 0.9em; text-align: center">The center of my online universe.</div>
</div>
<p>At some point not too long ago, I started signing up for services on the web.&nbsp; Gmail, Flickr, WordPress, Twitter, Facebook &#8230; ugh.&nbsp; I find lately I just can&#8217;t deal with it.&nbsp; As much as possible, I want everything in one place.&nbsp; There is simply no company doing this better than Google, which is becoming the center of my online universe:</p>
<ul>
<li>my photos: Google Photos + Picasa</li>
<li>my email: Gmail</li>
<li>my docs: Google Docs</li>
<li>my status: Google+ / Twitter</li>
<li>my contacts: Google contacts</li>
<li>my calendar: Google calendar</li>
</ul>
<p>The list goes on with Analytics, Adsense, web admin tools, etc.</p>
<p>It&#8217;s funny that I tried Google last for photos.&nbsp; For some reason I had it in my head that Picasa was a toy.&nbsp; I was wrong.&nbsp; I was delighted when I liked both their tool and service as it meant I could pile one more thing into my Google account.&nbsp; If one of your criteria is consolidation then Google is by far the leader.</p>
<h2>Final Thoughts </h2>
<p>Aperture + Picasa is a solid solution.&nbsp; As noted earlier though, it meets my needs.&nbsp; I don&#8217;t want to imply that tools like Lightroom aren&#8217;t good.&nbsp; They most certainly are for different tasks.&nbsp; To use my own integration argument, if you&#8217;re a heavy Adobe Creative Suite user, you&#8217;ll probably love Lightroom.&nbsp; The same goes for the other services mentioned.</p>
<p>I&#8217;m particularly interested in optimal workflows, i.e., the fastest path for getting from the camera to the web while also collecting/organizing things nicely on my system, applying meta data, etc.&nbsp; I&#8217;d love to hear your thoughts if you have found ways that work well for you.</p>
]]></content:encoded>
			<wfw:commentRss>http://markmcb.com/2011/10/28/3-reasons-aperture-and-picasa-are-a-great-photo-combo/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Symbolic Links to Image Folders in Rails 3.1</title>
		<link>http://markmcb.com/2011/08/22/symbolic-links-to-image-folders-in-rails-3-1/</link>
		<comments>http://markmcb.com/2011/08/22/symbolic-links-to-image-folders-in-rails-3-1/#comments</comments>
		<pubDate>Mon, 22 Aug 2011 16:04:14 +0000</pubDate>
		<dc:creator>markmcb</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[capistrano]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rails 3.1]]></category>
		<category><![CDATA[symlink]]></category>

		<guid isPermaLink="false">http://markmcb.com/?p=369</guid>
		<description><![CDATA[I recently tweaked the code for OmniNerd.com to upgrade it from a Rails 2.3 app to a Rails 3.1 app.  Online docs got me through everything but one item: symbolic links to folder of images (or assets in general).  On &#8230; <a href="http://markmcb.com/2011/08/22/symbolic-links-to-image-folders-in-rails-3-1/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I recently tweaked the code for <a href="http://www.omninerd.com/">OmniNerd.com</a> to upgrade it from a Rails 2.3 app to a Rails 3.1 app.  Online docs got me through everything but one item: symbolic links to folder of images (or assets in general).  On OmniNerd, users can upload images.  The site also auto-generates a lot of graphical content.  Our setup is like many, i.e., we deploy with Capistrano and use the shared folder to hold static user content that gets handed off between deployments.  We previously simply had a symlink setup such that:</p>
<pre class="brush: bash; light: true; title: ; notranslate">
/path/to/app/current/public/images/content --&gt; /path/to/app/shared/user_uploaded
</pre>
<p><span id="more-369"></span><br />
Now with Rails 3.1, during deployment statics assets are precompiled and end up in the folder:</p>
<pre class="brush: bash; light: true; title: ; notranslate">
/path/to/app/current/public/assets
</pre>
<p>This wasn&#8217;t immediately clear to me because it hadn&#8217;t crossed my mind to update the symlink and oddly enough, deploying with the old setup still sort of worked.  By &#8220;sort of,&#8221; I mean that about 1 in 20 images would come back as a 404.  That&#8217;s right, Rails would find some, but not others.  I still have no idea why that&#8217;s true, but the fix is quite simple.  I just updated my deploy script to create the following symlink:</p>
<pre class="brush: bash; light: true; title: ; notranslate">
/path/to/app/current/public/assets/content --&gt; /path/to/app/shared/user_uploaded
</pre>
<p>Note: be sure to precompile your assets before creating the link as the <code>/public/assets</code> folder is created on the fly during deployment when you precompile.</p>
<p>Hope that helps someone dealing with the same unpredictable 404s I was experiencing.</p>
]]></content:encoded>
			<wfw:commentRss>http://markmcb.com/2011/08/22/symbolic-links-to-image-folders-in-rails-3-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CrashPlan for Large, Distributed, Cheap, Off-Site Backup</title>
		<link>http://markmcb.com/2011/07/31/crashplan-for-large-distributed-cheap-off-site-backup/</link>
		<comments>http://markmcb.com/2011/07/31/crashplan-for-large-distributed-cheap-off-site-backup/#comments</comments>
		<pubDate>Sun, 31 Jul 2011 17:56:43 +0000</pubDate>
		<dc:creator>markmcb</dc:creator>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Server Administration]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[crashplan]]></category>
		<category><![CDATA[data]]></category>

		<guid isPermaLink="false">http://markmcb.com/?p=357</guid>
		<description><![CDATA[In the early 90s, my friend&#8217;s father took me to EDS where he worked at the time.  I remember him saying, &#8220;this is one of the largest data centers in the world.  They have over 3 terabytes of data in &#8230; <a href="http://markmcb.com/2011/07/31/crashplan-for-large-distributed-cheap-off-site-backup/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In the early 90s, my friend&#8217;s father took me to EDS where he worked at the time.  I remember him saying, &#8220;this is one of the largest data centers in the world.  They have over 3 terabytes of data in there.&#8221;  In the homemade box tucked away quietly in my hall closet is a 6x1TB RAID with another 1TB disk for the OS.  Add in the media center and 3 laptops and I&#8217;ve got a lot of data just waiting to be lost with a disk failure, theft, or an accidental <code>rm -rf</code>.</p>
<h2>What I Need in a Backup Solution</h2>
<p>As I thought about my data, I came up with a few criteria before I started scouring the net for a solution.</p>
<ol>
<li>No constraints on backup size &#8211; The data I want to backup exceeds 2TB and is growing.  I&#8217;ve used cool apps like DropBox that have arbitrary upper limits like 100GB.  However, the coolest app though won&#8217;t do me any good if I can&#8217;t backup everything I need. (To be fair, backup is just one tiny element of what DropBox does.  I highly recommend that app for the other things it does, like sync.)</li>
<li>Highly configurable &#8211; That 2TB I mentioned lives amongst tons of other stuff that I keep as sort of a cache, but wouldn&#8217;t miss it too much if it got deleted.  I need to be able to clearly specify what data I actually want backed up.  Moreover, I need a high degree of control about backup policies, security, etc.  I like solutions that make things simple, but in this case there also needs to be a way to get as complicated as I like.</li>
<li>Distributed backups &#8211; Part of the reason I have that 6x1TB RAID array is for super-fast local backup.  Obviously that won&#8217;t do me any good if my house burns down, but if a laptop crashes is way easier to grab 500GB from a local machine than it is to pull it across the net.  I want to be able to backup to a service as well as many other computers that I specify both in my house and on the Internet.</li>
<li>Smart, low profile application &#8211; Modern OS&#8217;s like Mac OS X keep a log of what files have changed.  I don&#8217;t want a dumb service that does things like that on its own and consumes my computers&#8217; resources.  I need something that will run in the background and not make any noise.</li>
<li>Accessibility &#8211; I need a service that runs on any platform, specifically Mac OS X and Linux.  Moreover, I need to be able to access my backups from the web.</li>
<li>Cheap &#8211; I want to pay for storage, not bandwidth.  Less than $10/mo is my general rule of thumb.</li>
</ol>
<p>There are other minor points, but those are the non-negotiable items.</p>
<p><span id="more-357"></span></p>
<h2>What I Tried, But Didn&#8217;t Like</h2>
<ol>
<li><a href="http://www.rackspace.com/cloud/cloud_hosting_products/files/">RackSpace Cloud Files</a> &#8211; great for storing files related to a web service, but ultimately too costly and would really only provide a storage point, i.e., no real app dedicated for backup.  (I only considered this because I use RackSpace for web hosting, at which they are quite good.)</li>
<li><a href="http://www.backblaze.com/">BackBlaze</a> &#8211; Great service and app for a novice user.  Ultimately it failed big for criteria 2 and 3 above though.  The service is strongly opinionated about what you can&#8217;t backup.  Also, you pay per computer.  If you&#8217;ve got 1 then $5 a month isn&#8217;t much, but obviously $5 per computer can add up quickly ($25 in my case).</li>
</ol>
<p><img class="alignright size-full wp-image-360" title="CrashPlan" src="http://markmcb.com/wp-content/uploads/2011/07/crashplan.png" alt="CrashPlan" width="185" height="97" /></p>
<p><span class="Apple-style-span" style="color: #000000; font-size: 22px; line-height: 32px;">The Solution: CrashPlan</span></p>
<p><a href="http://www.crashplan.com/">CrashPlan</a> is rad.</p>
<p>I purchased their CrashPlan+ plan.  $6/mo for all my computers and unlimited backup storage space.  The software is pretty great too. Highly configurable, good encryption, nice online support, runs on Win/Mac/Linux, and barely consumes any system resources when active (and can be active as a background/headless process).</p>
<p>As an example, the laptop I&#8217;m on now backs up in 3 ways:</p>
<ol>
<li>Time machine to a Linux share on my local RAID. Why: nice UI, quick access for day-to-day type stuff, good to have for a total failure.  (This option has nothing to do with CrashPlan.)</li>
<li>CrashPlan to a Linux share on my local RAID.  Why: backs up my critical files locally in a manner that allows me to access them easily from any home machine.  The method in option 1 has been problematic in the past, so this makes me feel a little better that the Apple-way doesn&#8217;t result in a loss of data. (Read more on sparsebundles if you&#8217;re curious.)  In addition, it&#8217;s lightning fast.</li>
<li>CrashPlan to a CrashPlan server.  Why: full off-site backup.  In addition to encrypting based on my login/password, they also allow you encrypt with a private key, which means even the folks at CrashPlan can&#8217;t see my data.  This is the ultimate backup.  If I was ever unfortunate enough to lose all my computers, I would be able to get my data back from this service.  Moreover, this allows me to access my backed-up data from anywhere in the world.</li>
</ol>
<h2>Final Thoughts</h2>
<p>There are many other solutions out there, so please consider your own criteria and pick the best one.  That said, if you ever find a solution that compares to CrashPlan on the criteria I&#8217;ve mentioned, I&#8217;d love to hear about it.</p>
<p>Also, I had a great conversation with a friend about smart sync when multiple computers are involved.  If that&#8217;s a requirement, I recommend checking out <a href="https://www.dropbox.com/">DropBox</a> or the like.  While CrashPlan syncs your computer with the backup, it does not attempt to sync all of your computers to have the same versions of files.  Using something like DropBox in conjunction with CrashPlan is a great option.</p>
]]></content:encoded>
			<wfw:commentRss>http://markmcb.com/2011/07/31/crashplan-for-large-distributed-cheap-off-site-backup/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>5TB LVM Volume with an LSI 9265-8i RAID Controller</title>
		<link>http://markmcb.com/2011/06/11/5tb-lvm-volume-with-an-lsi-9265-8i-raid-controller/</link>
		<comments>http://markmcb.com/2011/06/11/5tb-lvm-volume-with-an-lsi-9265-8i-raid-controller/#comments</comments>
		<pubDate>Sun, 12 Jun 2011 04:41:05 +0000</pubDate>
		<dc:creator>markmcb</dc:creator>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Server Administration]]></category>
		<category><![CDATA[9265-8i]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[lsi]]></category>
		<category><![CDATA[lvm]]></category>
		<category><![CDATA[raid]]></category>

		<guid isPermaLink="false">http://markmcb.com/?p=335</guid>
		<description><![CDATA[This article outlines how to get a 5TB LVM volume created with an LSI 9265-8i RAID controller. Background I&#8217;ve been running software RAID for a while. Specifically, I&#8217;ve got an ASUS P6T Deluxe V2 motherboard with 6 SATA ports. Up &#8230; <a href="http://markmcb.com/2011/06/11/5tb-lvm-volume-with-an-lsi-9265-8i-raid-controller/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This article outlines how to get a 5TB LVM volume created with an LSI 9265-8i RAID controller.</p>
<h2>Background</h2>
<div style="float: right; margin-left: 15px;"><a title="RAID Array by markmcb, on Flickr" href="http://www.flickr.com/photos/67712476@N00/5822915323/"><img src="http://farm6.static.flickr.com/5183/5822915323_ff4b08a789.jpg" alt="RAID Array" width="333" height="500" /></a></div>
<p>I&#8217;ve been running software RAID for a while. Specifically, I&#8217;ve got an ASUS P6T Deluxe V2 motherboard with 6 SATA ports. Up until now, I&#8217;ve had 1 SATA connected to a single 1 TB drive with the Fedora OS on it, one to a SATA DVD/Blu-ray drive, and the other 4 to a 4x1TB software RAID 5. This has worked great. When I started to max that out, I had a decision to make. It seems I could either:</p>
<ul>
<li>Continue with the small array and just continue to increase the disk size.  This is easiest, but given that 4 disks in RAID 5 give you a 25% loss of storage space (i.e., 3 used, 1 for parity), you have to buy bigger disks and the biggest ones usually cost the most.</li>
<li>Make the 1-time investment to get an 8-port RAID card and grow the array with disks that are large, but not necessarily the largest out there.</li>
</ul>
<p>I decided latter made more sense for me and went with the <a title="LSI Product Page for the 9265-8i RAID Controller" href="http://www.lsi.com/products/storagecomponents/Pages/MegaRAIDSAS9265-8i.aspx">LSI 9265-8i</a> based on various reviews.  My plan was to build a 6x1TB SATA array (5TB storage) with 2 available ports on which I could add 2 additional drives when/if needed.</p>
<p><span id="more-335"></span></p>
<h2>The Frustration</h2>
<p>I had two major issues right away.  The first was with WEBBIOS.  It&#8217;s a BIOS utility that&#8217;s supposed to allow you to configure your card as your system boots up by pressing CTRL+H when prompted.  Unfortunately for me, every time I would press it, the prompt would disappear and my system would boot normally.  This is still an issue, but the rest of the post works around it.</p>
<p>The second issue is that I couldn&#8217;t get the MegaRAID software installed in Fedora.  Again, this is supposed to be a bunch of tools that allow me to control my card, but instead it just gave me a lot of headaches with no results.  Every time I would try to install the software, it would complain about missing dependencies, etc.  This is also still an issue, but I have no work around.  (If you have ideas, I&#8217;m all ears.)</p>
<h2>Getting It To Work Without WEBBIOS</h2>
<p>At the same time you&#8217;re prompted to press CTRL+H, you&#8217;re also given the option to press CTRL+Y to go into the Preboot CLI (command line interface).  I thought, &#8220;hooray, I&#8217;m good at the command line.&#8221;  I soon found out it&#8217;s the <a href="http://www.kaltenbrunner.cc/blog/index.php?/archives/4-LSIlogic-MegaRAID-SAS-and-the-self-explaining-CLI.html">most cryptic</a>, undocumented CLI ever.  However, it does work.  Here&#8217;s what I did:</p>
<h3>Press CTRL-Y When Prompted</h3>
<p>This will take you into the CLI.  Note, that you&#8217;ll probably want to throw &#8220;-page20&#8243; at the end of all of the commands below.  This will make them only output 20 lines at a time, which is the only way to make sense of the ton of output it gives.</p>
<h3>Check Out What&#8217;s Going On</h3>
<p>Before building your array, you&#8217;ll want to check out the how things look before you touch them.  Unless you&#8217;ve got more than 1 card, your adapter number is 0.  You&#8217;ll see -a0 a lot in the lines below.</p>
<pre class="brush: bash; light: true; title: ; notranslate">-AdpAllInfo -a0</pre>
<p>That&#8217;s the mother lode.  It shows you EVERYTHING.  <strong>Take note of your enclosure devise number</strong>.  Mine is 252.  I&#8217;ll use 252 for the rest of the article, but you should use your number.</p>
<pre class="brush: bash; light: true; title: ; notranslate">-PDList -a0</pre>
<p>This will give you detailed info on each drive you have.  I recommend you use the serial numbers shown along with the slot numbers to physically label your cables if you haven&#8217;t already.</p>
<h3>Build the Array</h3>
<p>Once you&#8217;ve collected all the info you need, build the array.</p>
<pre class="brush: bash; light: true; title: ; notranslate">
-CfgLdAdd -r5 [252:0, 252:1, 252:2, 252:3, 252:4, 252:5] -a0
</pre>
<ul>
<li>-r5 means RAID 5</li>
<li>:0, :1, :2, etc., are the ports my drives are on</li>
<li>252 is my enclosure device number</li>
<li>0 is my adapter</li>
</ul>
<p>Tada!  You&#8217;re ready to get going in your OS.  (HUGE thanks to Moritz Mertinkat for putting together <a title="MegaRaid CLI Cheat Sheet" href="http://tools.rapidsoft.de/perc/perc-cheat-sheet.html">this cheat sheet</a>, which helped quite a bit.)</p>
<h2>Creating a 5TB LVM</h2>
<p>The bottom line here is: don&#8217;t create a partition for a volume this size.  You&#8217;ll find out that it maxes out a 2TB and you&#8217;ll be left scratching your head.  Instead, we&#8217;re just going to create the standard <a href="http://en.wikipedia.org/wiki/GUID_Partition_Table">GUID Partition Table</a> layout, but not actually put any sort of actual partition on it.</p>
<pre class="brush: bash; light: true; title: ; notranslate">
# parted
(parted) mklabel gpt
(parted) mkpart primary 0 4998GB
[Ignore the warning you get here.  That's expected and ok.]
(parted) quit
</pre>
<p>Create the Physical Volume:</p>
<pre class="brush: bash; light: true; title: ; notranslate">
# pvcreate /dev/sdb1
</pre>
<p>Create the Volume Group (I called mine vg_store):</p>
<pre class="brush: bash; light: true; title: ; notranslate">
# vgcreate -s 256M vg_store /dev/sdb1
</pre>
<p>Create the Logical Volume (I called mine lv_store):</p>
<pre class="brush: bash; light: true; title: ; notranslate">
# lvcreate -L 4640G -n lv_store vg_store
</pre>
<p>Format the volume.  (I used ext4):</p>
<pre class="brush: bash; light: true; title: ; notranslate">
# mke2fs -t ext4 /dev/vg_store/lv_store
</pre>
<p>Make a folder in which to mount the volume (wherever you like):</p>
<pre class="brush: bash; light: true; title: ; notranslate">
# mkdir /mnt/store
</pre>
<p>Mount the volume (you may also want to edit /etc/fstab)</p>
<pre class="brush: bash; light: true; title: ; notranslate">
# mount -t ext4 /dev/mapper/vg_store-lv_store /mnt/store/
</pre>
<p>Enjoy your new GIANT storage volume!</p>
]]></content:encoded>
			<wfw:commentRss>http://markmcb.com/2011/06/11/5tb-lvm-volume-with-an-lsi-9265-8i-raid-controller/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Converting VHS to Digital Video (DV) With Canopus (Grass Valley) ADVC-300</title>
		<link>http://markmcb.com/2010/12/28/converting-vhs-to-digital-video-dv-with-canopus-grass-valley-advc-300/</link>
		<comments>http://markmcb.com/2010/12/28/converting-vhs-to-digital-video-dv-with-canopus-grass-valley-advc-300/#comments</comments>
		<pubDate>Tue, 28 Dec 2010 17:31:36 +0000</pubDate>
		<dc:creator>markmcb</dc:creator>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[archive]]></category>
		<category><![CDATA[dv]]></category>
		<category><![CDATA[tape]]></category>
		<category><![CDATA[vhs]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://markmcb.com/blog/?p=296</guid>
		<description><![CDATA[My parents have mountains of VHS tapes that are slowly degrading in various boxes, cabinets and shelves throughout their house.  For Christmas, I got them a Canopus (now Grass Valley) ADVC-300.  The results were pretty awesome.  Here&#8217;s what we did: &#8230; <a href="http://markmcb.com/2010/12/28/converting-vhs-to-digital-video-dv-with-canopus-grass-valley-advc-300/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img style="float: right; width: 275px; height: 125px" title="IMG_0138.jpg" src="http://markmcb.com/wp-content/uploads/2010/12/IMG_0138.jpg" border="0" alt="Canopus / Grass Valley ADVC-300" width="275" height="125" />My parents have mountains of VHS tapes that are slowly degrading in various boxes, cabinets and shelves throughout their house.  For Christmas, I got them a <a href="http://www.grassvalley.com/products/advc300">Canopus (now Grass Valley) ADVC-300</a>.  The results were pretty awesome.  Here&#8217;s what we did:</p>
<ol>
<li>Purchased the ADVC-300 online from Electronica Direct via Amazon. </li>
<li>Went to Wal-Mart and got the cheapest VHS player they had.  I think this is important.  If you&#8217;ve got a ton of videos to convert, make sure you have a player that&#8217;s ready for the load.  If you dig out the old player from 1987, you might get poor results.</li>
<li>Went to Best Buy and got a Firewire 400 to 800 converter cable.  The ADVC-300 comes with a 400 to mini-400 cable, but my parents have a newer iMac that has a Firewire 800 port so the extra cable was necessary.</li>
<li>Plugged everything in: VHS player to ADVC-300 to iMac</li>
<li>Opened iMovie, clicked import, pressed play on the VHS player</li>
</ol>
<p>The results were very nice.  Obviously quality is determined by the tapes, but the process was generally hassle free.  The only pain point was that iMovie stops importing every time it reaches empty tape.  So if you&#8217;ve got several things on one tape and a few seconds between each video set, then iMovie will stop importing at the end of each and you&#8217;ll have to manually restart the import for the next set.  I&#8217;m guessing that if you used a &#8220;pro&#8221; application like Final Cut, this could probably be avoided.</p>
<p>If you&#8217;ve got a stockpile, now&#8217;s the time.  I found tapes with mold in the cassette and one tape broke during playback due to brittle plastic.  I&#8217;m glad we converted to DV because I&#8217;m not sure those tapes would last much longer and it would be a shame to lose 20+ years of video records.</p>
<p>Bottom line: the ADVC-300 is a solid purchase for anyone looking to convert VHS tapes to digital video.</p>
]]></content:encoded>
			<wfw:commentRss>http://markmcb.com/2010/12/28/converting-vhs-to-digital-video-dv-with-canopus-grass-valley-advc-300/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lunchpool Alpha Launched!</title>
		<link>http://markmcb.com/2010/12/05/lunchpool-alpha-launched/</link>
		<comments>http://markmcb.com/2010/12/05/lunchpool-alpha-launched/#comments</comments>
		<pubDate>Mon, 06 Dec 2010 03:08:08 +0000</pubDate>
		<dc:creator>markmcb</dc:creator>
				<category><![CDATA[Lunchpool]]></category>
		<category><![CDATA[app]]></category>
		<category><![CDATA[food]]></category>
		<category><![CDATA[lunch]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://markmcb.com/blog/?p=286</guid>
		<description><![CDATA[At work, people constantly order food.  The process is something like this: invite 15 people to a meeting, order food for 20 &#8220;just in case,&#8221; post a call-in number on the meeting, have 10 people actually attend in person with &#8230; <a href="http://markmcb.com/2010/12/05/lunchpool-alpha-launched/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a rel="attachment wp-att-288" href="http://markmcb.com/2010/12/05/lunchpool-alpha-launched/brown_bag/"><img class="alignright size-full wp-image-288" title="Lunchpool" src="http://markmcb.com/wp-content/uploads/2010/12/brown_bag.png" alt="" width="225" height="225" /></a>At work, people constantly order food.  The process is something like this: invite 15 people to a meeting, order food for 20 &#8220;just in case,&#8221; post a call-in number on the meeting, have 10 people actually attend in person with at least 2-3 not eating for various reasons.  Result: tons (literally) of wasted food per week.</p>
<p>Last week I launched a new web app called <a href="http://lunchpool.com">Lunchpool</a>.  It&#8217;s purpose is to deal with the situation above.  If know where extra food is, you post it.  Your post is limited to people at your domain, so if my company&#8217;s email address ends in @example.com, then only people with the same email domain can see my post.  Throw in some building, floor, and food info with your post and alert people when new stuff is posted and the scavengers come out of the woodwork.</p>
<p>I&#8217;ll be curious to see how it goes over the next few weeks.  If you&#8217;ve got a company, school, organization, etc., with a unique domain and you&#8217;d like to be a part of the alpha test shoot me a note using the contact info on Lunchpool.</p>
]]></content:encoded>
			<wfw:commentRss>http://markmcb.com/2010/12/05/lunchpool-alpha-launched/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Install markItUp! in Ruby on Rails</title>
		<link>http://markmcb.com/2008/11/08/install-markitup-in-ruby-on-rails/</link>
		<comments>http://markmcb.com/2008/11/08/install-markitup-in-ruby-on-rails/#comments</comments>
		<pubDate>Sat, 08 Nov 2008 18:43:57 +0000</pubDate>
		<dc:creator>markmcb</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[maritup]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[redcloth]]></category>
		<category><![CDATA[textile]]></category>

		<guid isPermaLink="false">http://markmcb.com/?p=256</guid>
		<description><![CDATA[If you&#8217;re torn between a WYSIWYG editor and something clean like Textile/Redcloth, then markItUp! will provide you with some nice middle ground. The tool is well documented, but there are a few &#8220;notes&#8221; for installing it in Rails that aren&#8217;t &#8230; <a href="http://markmcb.com/2008/11/08/install-markitup-in-ruby-on-rails/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re torn between a WYSIWYG editor and something clean like Textile/Redcloth, then <a href="http://markitup.jaysalvat.com/">markItUp!</a> will provide you with some nice middle ground. The tool is well documented, but there are a few &#8220;notes&#8221; for installing it in Rails that aren&#8217;t in the <a href="http://markitup.jaysalvat.com/documentation/">docs</a>.</p>
<h3>1. Initial setup</h3>
<p>Since there&#8217;s overhead associated with markItUp!, I set a variable <code>@content_submission</code> to true so that my standard layout template can skip all of the extra javascript when it&#8217;s not necessary. To keep things simple, I&#8217;m going to follow the markItUp! hierarchy, which means it&#8217;s stylesheets will be in your javascripts path.</p>
<p><span id="more-256"></span></p>
<p>Install jQuery into your javascripts folder along with markItUp!. Download whatever markItUp! set you want to use (I&#8217;m using textile above, which assumes you&#8217;ve already ran <code>sudo gem install redcloth</code>) and drop that in the sets folder. All of this is documented in the standard <a href="http://markitup.jaysalvat.com/documentation/">markItUp! docs</a>. You only need to make one edit to the standard markItUp! file. In jquery.markitup.js, edit <code> previewTemplatePath</code> to the following:</p>
<pre class="brush: jscript; title: ; notranslate">previewTemplatePath:	'/javascripts/markitup/templates/preview.html'</pre>
<h3>2. Add an action to parse the text</h3>
<p>I&#8217;ve got a controller called <code>content_controller</code> that will handle my Textile processing with Redcloth. I&#8217;ve defined an action as follows:</p>
<pre class="brush: ruby; title: ; notranslate">def parse_textile
  render :text =&amp;gt; RedCloth.new(params[:data]).to_html
end</pre>
<p>You may want to add more to this action to provide security.</p>
<h3>3. Add a route to for your new action</h3>
<p>Assuming you&#8217;re using RESTful routes, just modify your existing route:</p>
<pre class="brush: ruby; title: ; notranslate">map.resources :content, :member =&amp;gt; {:parse_textile =&amp;gt; :post}</pre>
<h3>4. Tell markItUp! about your route</h3>
<p>Lastly, edit your set file and tell it about the route:</p>
<pre class="brush: jscript; title: ; notranslate">previewParserPath:	'/content/parse_textile'</pre>
]]></content:encoded>
			<wfw:commentRss>http://markmcb.com/2008/11/08/install-markitup-in-ruby-on-rails/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ruby on Rails Diff Text to HTML &lt;ins&gt; and &lt;del&gt;</title>
		<link>http://markmcb.com/2008/11/04/ruby-on-rails-diff-text-to-html-ins-and-del/</link>
		<comments>http://markmcb.com/2008/11/04/ruby-on-rails-diff-text-to-html-ins-and-del/#comments</comments>
		<pubDate>Wed, 05 Nov 2008 00:12:11 +0000</pubDate>
		<dc:creator>markmcb</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[del]]></category>
		<category><![CDATA[diff]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[ins]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://markmcb.com/?p=243</guid>
		<description><![CDATA[This code is perfect if you have 2 text objects in your Rails application and you want to compare their differences in one of your HTML views. It&#8217;s 99% pure Ruby too, so if you alter the first line, you &#8230; <a href="http://markmcb.com/2008/11/04/ruby-on-rails-diff-text-to-html-ins-and-del/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This code is perfect if you have 2 text objects in your Rails application and you want to compare their differences in one of your HTML views.  It&#8217;s 99% pure Ruby too, so if you alter the first line, you can use it for other purposes.</p>
<p>Only one thing to note: you must have diff installed.  I&#8217;m using: diff (GNU diffutils) 2.8.1.</p>
<pre class="brush: ruby; title: ; notranslate">
#set up some variables to reference later
temporary_directory = File.join(Rails.root, &quot;tmp&quot;)
max_lines = 9999999 #needs to be larger than the most lines you'll consider
diff_header_length = 3

# text_old and text_new should be the values of the string objects to compare
# these are just example strings to show it works
text_old      = &quot;line1\ndeleted line2\nline3\n\nline4\nline5&quot;
text_new      = &quot;line1\ninserted line2\nline3\n\nline4\nline5&quot;

# since we're using diff on the file system, we'll save the text we want to compare
# and then run diff against the two files
file_old_name = File.join(temporary_directory,&quot;file_old&quot;+rand(1000000).to_s)
file_new_name = File.join(temporary_directory,&quot;file_new&quot;+rand(1000000).to_s)
file_old      = File.new(file_old_name, &quot;w+&quot;)
file_new      = File.new(file_new_name, &quot;w+&quot;)
file_old.write(text_old+&quot;\n&quot;)
file_new.write(text_new+&quot;\n&quot;)
file_old.close
file_new.close

# diff will give provide a string showing insertions and deletions.  We will
# split this string out by newlines if there are difference, and mark it up
# accordingly with html
lines = %x(diff -­-­­­­­­unified=#{max_lines} #{file_old_name} #{file_new_name})
if lines.empty?
  lines = text_new.split(/\n/)
else
  lines = lines.split(/\n/)[diff_header_length..max_lines].
  collect do |i|
    if i.empty?
      &quot;&quot;
    else
      case i[0,1]
      when &quot;+&quot;; then &quot;&lt;ins&gt;&quot;+i[1..i.length-1]+&quot;&lt;/ins&gt;&quot;
      when &quot;-&quot;; then &quot;&lt;del&gt;&quot;+i[1..i.length-1]+&quot;&lt;/del&gt;&quot;
      else; i[1..i.length-1]
      end
    end
  end
end

#clean up the temporary diff files we created
File.delete(file_new_name)
File.delete(file_old_name)

#return marked up text
lines.join(&quot;\n&quot;)&lt;/pre&gt;
If you fire up RAILS_ROOT/script/console and paste that code in, it will return a nicely marked up string like this:
&lt;pre lang=&quot;html&quot;&gt;line1
&lt;del&gt;deleted line2&lt;/del&gt;
&lt;ins&gt;inserted line2&lt;/ins&gt;
line3

line4
line5
</pre>
<p>Use CSS to make your ins and del tags render however you like.</p>
]]></content:encoded>
			<wfw:commentRss>http://markmcb.com/2008/11/04/ruby-on-rails-diff-text-to-html-ins-and-del/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
<!-- This Quick Cache file was built for (  markmcb.com/feed/ ) in 0.22547 seconds, on May 18th, 2012 at 10:18 am UTC. -->
<!-- This Quick Cache file will automatically expire ( and be re-built automatically ) on May 18th, 2012 at 11:18 am UTC -->
<!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<!-- Quick Cache Is Fully Functional :-) ... A Quick Cache file was just served for (  markmcb.com/feed/ ) in 0.00042 seconds, on May 18th, 2012 at 10:28 am UTC. -->
