<?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>SmartLogic Solutions Blog &#187; Joseph Jakuta</title>
	<atom:link href="http://blog.smartlogicsolutions.com/category/joseph-jakuta/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.smartlogicsolutions.com</link>
	<description>News and updates from the people at SmartLogic Solutions</description>
	<lastBuildDate>Tue, 30 Nov 2010 21:39:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>using active x and javascript to scan from your web app</title>
		<link>http://blog.smartlogicsolutions.com/2008/08/08/using-active-x-and-javascript-to-scan-from-your-web-app/</link>
		<comments>http://blog.smartlogicsolutions.com/2008/08/08/using-active-x-and-javascript-to-scan-from-your-web-app/#comments</comments>
		<pubDate>Fri, 08 Aug 2008 16:57:18 +0000</pubDate>
		<dc:creator>Joseph Jakuta</dc:creator>
				<category><![CDATA[ActiveX]]></category>
		<category><![CDATA[Adobe PDF]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Joseph Jakuta]]></category>

		<guid isPermaLink="false">http://blog.smartlogicsolutions.com/?p=125</guid>
		<description><![CDATA[In the app I had been working on users had to perform a great amount of scanning. In the first few iterations this was done manually, which, of course, lead to lots of user error (namely scanning documents at high resolutions, which clogged the system). It was decided that it was best if our app [...]]]></description>
			<content:encoded><![CDATA[<p>In the app I had been working on users had to perform a great amount of scanning.  In the first few iterations this was done manually, which, of course, lead to lots of user error (namely scanning documents at high resolutions, which clogged the system).  It was decided that it was best if our app to control the scan settings for most users.  So we found three possible Active X controllers available to allow for this functionality.  <a href="http://www.ciansoft.com/" target="new">CianSoft</a>, <a href="http://www.vintasoft.com/vstwain-index.html" target="new">VintaSoft</a>, and <a href="http://www.chestysoft.com/" target="new">ChestySoft</a>.  After a little research we found that VintaSoft didn&#8217;t quite meet our needs and that CianSoft&#8217;s TwainX controller and ChestySoft&#8217;s were eerily similar (it turns out that each company is run by a brother and both products were just different flavors of the same one).  In the end ChestySoft was the one we went with because it allows you to perform posts of the scanned data to the server (and the guy that runs the company is super responsive when you have questions).  </p>
<p><span id="more-125"></span></p>
<p>First there isn&#8217;t too much to get this ActiveX controller up in running in the first place.  There are great examples <a href="http://www.chestysoft.com/ximage/manual.htm#sect2" target="new">here</a> that take you 95% of the way towards getting these up and running.  A few little tricks we learned when setting up the javascript portion of the code are as follows:</p>
<ul>
<li>To set the page size use the following method (the example sets it to letter):

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">      csxi.<span style="color: #660066;">SetTwainLayout</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span><span style="color: #CC0000;">8.5</span><span style="color: #339933;">,</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span><span style="color: #CC0000;">11</span><span style="color: #009900;">&#41;</span></pre></div></div>

</li>
<li>Some scanners do not reset to their defaults after a custom scan.  You need to make sure you manually set all default settings before scanning.  A few you may want to set:

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">      csxi.<span style="color: #660066;">UseTwainInterface</span><span style="color: #339933;">=</span><span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">//this makes sure that you are not prompted to change settings</span>
      csxi.<span style="color: #660066;">TwainAutoBright</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>
      csxi.<span style="color: #660066;">TwainAutoDeskew</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span></pre></div></div>

</li>
<li>When beginning a multipage scan you must run the following three methods:<br/>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">      csxi.<span style="color: #660066;">TwainMultiImage</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>
      csxi.<span style="color: #660066;">UseADF</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>
      csxi.<span style="color: #660066;">ClearPDF</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

</li>
</ul>
<p>One other fun thing we can do with ChestySoft&#8217;s TwainX controller is upload the captured data directly to the server.  To do this in the javascript you need to do the following:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">      Success <span style="color: #339933;">=</span> csxi.<span style="color: #660066;">PostImage</span><span style="color: #009900;">&#40;</span>url<span style="color: #339933;">,</span> file_name<span style="color: #339933;">,</span> param_name<span style="color: #339933;">,</span> graphics_format<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>Success<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">//what to do when success</span>
      <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">//what to do if error - here are recommendations:</span>
        csxi.<span style="color: #660066;">SaveToFile</span><span style="color: #009900;">&#40;</span>path_on_desktop<span style="color: #009900;">&#41;</span> <span style="color: #006600; font-style: italic;">//write data to desktop if you saved as a graphic; </span>
        csxi.<span style="color: #660066;">WritePDF</span><span style="color: #009900;">&#40;</span>path_on_desktop<span style="color: #009900;">&#41;</span> <span style="color: #006600; font-style: italic;">//write data to desktop if you saved as a pdf; </span>
      <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Some notes about the preceding code.  <i>url</i> a fully qualified url (including the &#8216;http://&#8217;).  <i>file_name</i> is what will be included as <i>original_filename</i> when you are reading data on the server side.  <i>graphics_format</i> is a enumeration that can be found <a href="http://www.chestysoft.com/ximage/manual.htm#sect19" target="new">here</a>.  </p>
<p>And the best thing is after you click on the button that runs your scan the information uploaded is the same as a standard file upload so you don&#8217;t have to do anything strange at all in ruby.</p>
<div id="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://blog.smartlogicsolutions.com/2010/10/08/testing-ajax-with-testunit/" rel="bookmark" class="crp_title">Testing AJAX with Test::Unit</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/10/15/using-swfobject-to-seamlessly-upgrade-to-flash-player-10/" rel="bookmark" class="crp_title">Using SWFObject to Seamlessly Upgrade to Flash Player 10</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/07/01/microsoft-webdav-opens-document-as-read-only-when-using-railsdav/" rel="bookmark" class="crp_title">Microsoft WebDav opens document as Read-Only when using RailsDav</a></li><li><a href="http://blog.smartlogicsolutions.com/2007/08/21/adobe-onair-bus-tour-baltimore/" rel="bookmark" class="crp_title">Adobe onAIR Bus Tour: Baltimore</a></li><li><a href="http://blog.smartlogicsolutions.com/2007/06/06/eclipse-32-and-out-of-memory-errors/" rel="bookmark" class="crp_title">Eclipse 3.2 and &#8220;Out Of Memory&#8221; errors</a></li><li>Powered by <a href="http://ajaydsouza.com/wordpress/plugins/contextual-related-posts/">Contextual Related Posts</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://blog.smartlogicsolutions.com/2008/08/08/using-active-x-and-javascript-to-scan-from-your-web-app/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Merging Adobe PDF&#8217;s and generating a table of contents on the fly using ruby</title>
		<link>http://blog.smartlogicsolutions.com/2008/07/21/adobe-pdfs-and-table-of-contents-on-the-fly/</link>
		<comments>http://blog.smartlogicsolutions.com/2008/07/21/adobe-pdfs-and-table-of-contents-on-the-fly/#comments</comments>
		<pubDate>Mon, 21 Jul 2008 17:06:09 +0000</pubDate>
		<dc:creator>Joseph Jakuta</dc:creator>
				<category><![CDATA[Adobe PDF]]></category>
		<category><![CDATA[Joseph Jakuta]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.smartlogicsolutions.com/?p=101</guid>
		<description><![CDATA[So let&#8217;s say you have some random PDFs and what you want is one PDF that includes all of the original PDF files and a table of contents listing all of the files and the proper page numbers. Well in Ruby it is not too hard to put this together. There are a wealth of [...]]]></description>
			<content:encoded><![CDATA[<p>So let&#8217;s say you have some random PDFs and what you want is one PDF that includes all of the original PDF files and a table of contents listing all of the files and the proper page numbers.  Well in Ruby it is not too hard to put this together.  There are a wealth of plugins, gems, and other ruby software available for manipulating and creating PDFs (a thorough list can be found here &#8211; <a href="http://wiki.rubyonrails.org/rails/pages/HowtoGeneratePDFs" target="new">http://wiki.rubyonrails.org/rails/pages/HowtoGeneratePDFs</a>).  To get this project up and running we are going to use two PDF::Writer (<a href="http://rubyforge.org/projects/ruby-pdf/" target="new">http://rubyforge.org/projects/ruby-pdf/</a>) and PDFTK (<a href="http://www.accesspdf.com/pdftk/" target="new">http://www.accesspdf.com/pdftk/</a>) &#8211; though if you want to get fancier and also include text, html, or xml documents you can use PDF::Htmldoc (<a href="http://htmldoc.rubyforge.org/" target="new">http://htmldoc.rubyforge.org/</a>) which requires Htmldoc to be installed.  Before I do get started though, I also have give thanks to George Anderson over at <a href="http://www.benevolentcode.com/" target="new">Benevolent Code</a> who wrote a lot of similar code on the project which provided me with some great examples.</p>
<p><span id="more-101"></span></p>
<p>In the project that I wrote this for we began by creating a wrapper class for the PDFTK gem mentioned earlier.  The basic shell of the method we will be using accepts a list of files and a a title for the new pdf and begins and ends by creating and removing temp directories respectively.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> PdfTool<span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">PDF::Toolkit</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">concat_and_make_table_of_contents</span><span style="color:#006600; font-weight:bold;">&#40;</span>title, files<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'pdf/writer'</span>
    <span style="color:#9966CC; font-weight:bold;">begin</span>
      tmpdir = make_temp<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">''</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#CC00FF; font-weight:bold;">FileUtils</span>.<span style="color:#9900CC;">mkdir</span><span style="color:#006600; font-weight:bold;">&#40;</span>tmpdir<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
       <span style="color:#008000; font-style:italic;">#the rest of the code is going here   </span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> error
      <span style="color:#CC0066; font-weight:bold;">raise</span> error
    <span style="color:#9966CC; font-weight:bold;">ensure</span>
      <span style="color:#CC00FF; font-weight:bold;">FileUtils</span>.<span style="color:#9900CC;">rm</span><span style="color:#006600; font-weight:bold;">&#40;</span>temppath<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Following this we are going to have set up PDF::Writer for creating the table of contents.  Unfortunately PDF::Writer is a bit messy to get going, but we are only going to be creating a table of contents with the simplest format possible so it will not be too bad.  Of course if you are not going to want this hard coded, we could easily rewrite the concat_and_make_table_of_contents so that it takes a hash of formatting variables.  Here is the set up of PDF:Writer as well printing of the title.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">      <span style="color:#0066ff; font-weight:bold;">@text_font</span> = <span style="color:#996600;">&quot;Times-Roman&quot;</span>
      <span style="color:#0066ff; font-weight:bold;">@title_font_size</span> = <span style="color:#006666;">17</span>
      <span style="color:#0066ff; font-weight:bold;">@title_vertical_spacing</span> = <span style="color:#006666;">15</span>
      <span style="color:#0066ff; font-weight:bold;">@page_font_size</span> = <span style="color:#006666;">12</span>
      <span style="color:#0066ff; font-weight:bold;">@page_vertical_spacing</span> = <span style="color:#006666;">8</span>
&nbsp;
      print_pdf = <span style="color:#6666ff; font-weight:bold;">PDF::Writer</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:paper</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;A4&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      print_pdf.<span style="color:#9900CC;">margins_pt</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">36</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@top_heading_font_position</span> = <span style="color:#006666;">10</span>
&nbsp;
      print_pdf.<span style="color:#9900CC;">select_font</span> <span style="color:#0066ff; font-weight:bold;">@text_font</span>
      print_pdf.<span style="color:#9900CC;">text</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;&lt;b&gt;#{title}&lt;/b&gt;&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:font_size</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@title_font_size</span>,:justification <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:center</span>,:left <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@top_heading_font_position</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      print_pdf.<span style="color:#9900CC;">move_pointer</span><span style="color:#006600; font-weight:bold;">&#40;</span>@title_vertical_spacing<span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Next we need to go through the files and generate the table of contents.  We will have a loop to check that all of the files in the array exist and are PDFs (though this will need to change if you decide to add in html, etc conversion).  Then we are going to start assuming the first page of the first document in the list is page 1 (if you want to include the table of contents in the page count you will mostly likely have to generate the table of contents once, then figure out how many pages is its then regenerate it with the offset &#8211;  but we are simplifying this for this example).  Following that we are going to loop though all of the files, determine the title from the metadata and print the title and the page number for each page.   This will finish up by saving the table of contents to a temp file.  (Note: don&#8217;t be confused we are keeping track of two pdf variables &#8211; pdf which corresponds to PDFTK instances and print_pdf which corresponds to PDF::Writer instances).</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">      files = files.<span style="color:#9900CC;">delete_if</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> !<span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">exists</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>f<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">||</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">mime_type</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>f<span style="color:#006600; font-weight:bold;">&#41;</span> != <span style="color:#996600;">'application/pdf'</span><span style="color:#006600; font-weight:bold;">&#125;</span>
      current_page=<span style="color:#006666;">1</span>
      files.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span>
        pdf = <span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>f<span style="color:#006600; font-weight:bold;">&#41;</span>
        page_title = <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#40;</span>pdf<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:Title</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">||</span> pdf<span style="color:#006600; font-weight:bold;">&#91;</span>:<span style="color:#CC00FF; font-weight:bold;">File</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">||</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">basename</span><span style="color:#006600; font-weight:bold;">&#40;</span>f<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        print_pdf.<span style="color:#9900CC;">text</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{page_title} - #{current_page}&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:font_size</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@page_font_size</span>,:justification <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:left</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        print_pdf.<span style="color:#9900CC;">move_pointer</span><span style="color:#006600; font-weight:bold;">&#40;</span>@page_vertical_spacing<span style="color:#006600; font-weight:bold;">&#41;</span>
        current_page<span style="color:#006600; font-weight:bold;">+</span>= pdf.<span style="color:#9900CC;">pages</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
      print_pdf.<span style="color:#9900CC;">save_as</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span>tmpdir,<span style="color:#996600;">'toc.pdf'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>You may have noticed one method in the previous code that needs some flushing out.  PDFTK provides accessors for all metadata that can be found in the pdf, you simply pass a symbol or a string to the [] method to retrieve it.  Furthermore you can use PDFTK to access the number of pages in the file by simply calling <i>pages</i>.  </p>
<p>For the last step we are going to concatenate all of the files that were passed in the array with the table of contents.  Again PDFTK will come in handy here.  There is a class method <i>pdftk</i> which will accept any commands that PDFTK will run as an array.  So all we need to do is have the PDFTK invoke the concat method.  Following that we are just going to read the data for the generated file and pass that back before we start rescuing and ensuring code.  This portion is as follows:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">      command = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span>tmpdir,<span style="color:#996600;">'toc.pdf'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">+</span> files <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'cat'</span>,<span style="color:#996600;">'output'</span>,<span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span>tmpdir, <span style="color:#996600;">'outfile.pdf'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#CC00FF; font-weight:bold;">IOError</span>, <span style="color:#996600;">&quot;Unknown PDFTK Error command: pdftk #{command.join(' ')}&quot;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> pdftk<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>command<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
      data = <span style="color:#0000FF; font-weight:bold;">nil</span>
      <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span>tmpdir, <span style="color:#996600;">'outfile.pdf'</span><span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#996600;">'r'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> data = f.<span style="color:#9900CC;">read</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
      <span style="color:#0000FF; font-weight:bold;">return</span> data</pre></div></div>

<p>So now we have a simple method for concatenating and creating a table of contents for several PDF files.</p>
<div id="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://blog.smartlogicsolutions.com/2008/06/02/new-acrobatcom-and-reader-9/" rel="bookmark" class="crp_title">New Acrobat.com and Reader 9</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/07/09/reading-and-replacing-text-in-word-docx-and-excel-xlsx-documents-using-ruby/" rel="bookmark" class="crp_title">Reading and replacing text in Word DocX and Excel XlsX documents using Ruby</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/08/08/using-active-x-and-javascript-to-scan-from-your-web-app/" rel="bookmark" class="crp_title">using active x and javascript to scan from your web app</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/06/13/ruby-on-rails-polymorphic-association-benchmarks/" rel="bookmark" class="crp_title">Ruby on Rails Polymorphic Association Benchmarks</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/08/04/introducing-environmentalize-an-intuitive-environment-focused-config-structure-for-your-rails-applications/" rel="bookmark" class="crp_title">Introducing environmentalist: an intuitive, environment-focused config structure for your rails applications</a></li><li>Powered by <a href="http://ajaydsouza.com/wordpress/plugins/contextual-related-posts/">Contextual Related Posts</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://blog.smartlogicsolutions.com/2008/07/21/adobe-pdfs-and-table-of-contents-on-the-fly/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Merging a :has_many relationship into one instance</title>
		<link>http://blog.smartlogicsolutions.com/2008/07/10/merging-a-has_many-relationship-into-one-instance/</link>
		<comments>http://blog.smartlogicsolutions.com/2008/07/10/merging-a-has_many-relationship-into-one-instance/#comments</comments>
		<pubDate>Thu, 10 Jul 2008 14:13:59 +0000</pubDate>
		<dc:creator>Joseph Jakuta</dc:creator>
				<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[Joseph Jakuta]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://blog.smartlogicsolutions.com/2008/07/10/merging-a-has_many-relationship-into-one-instance/</guid>
		<description><![CDATA[So the problem is that I have an ActiveRecord model that has a :has_many relationship to another model (we&#8217;ll call this one object), but when I am in the view context I didn&#8217;t want to have to loop through the object each time to determine which data was being displayed. Object has many attributes (approximately [...]]]></description>
			<content:encoded><![CDATA[<p>So the problem is that I have an ActiveRecord model that has a :has_many relationship to another model (we&#8217;ll call this one object), but when I am in the view context I didn&#8217;t want to have to loop through the object each time to determine which data was being displayed.  Object has many attributes (approximately 30) and many are often null for a given instance. So I decided to add a method to my model to loop through all of objects and determine which data should be included.  Pretty much the rule was that if there was no data for a particular attribute temporarily save it to a copy of the object and then return that.  This is what I came up with.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> object
    tmp = objects.<span style="color:#9900CC;">first</span>
    objects.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>o<span style="color:#006600; font-weight:bold;">|</span> tmp.<span style="color:#9900CC;">attributes</span>.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>key, value<span style="color:#006600; font-weight:bold;">|</span> tmp<span style="color:#006600; font-weight:bold;">&#91;</span>key<span style="color:#006600; font-weight:bold;">&#93;</span> = o<span style="color:#006600; font-weight:bold;">&#91;</span>key<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">if</span> value.<span style="color:#9900CC;">blank</span>? <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> key != <span style="color:#996600;">'id'</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
    tmp.<span style="color:#9900CC;">freeze</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>However there was a flaw here.  Every time I would view the page all of the data in the objects was getting overwritten with one copy of it.  After banging my head on the desk it was realized that tmp[key] = o[key] was actually writing the changes to the database permanently rewriting all of the objects (which still seems counter intuitive to me, because it seems like only the first record should have been the one changing).  But the solution was pretty simple.  The working method is as follows.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> object
    tmp = <span style="color:#CC00FF; font-weight:bold;">Object</span>.<span style="color:#9900CC;">new</span>
    objects.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>o<span style="color:#006600; font-weight:bold;">|</span> tmp.<span style="color:#9900CC;">attributes</span>.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>key, value<span style="color:#006600; font-weight:bold;">|</span> tmp<span style="color:#006600; font-weight:bold;">&#91;</span>key<span style="color:#006600; font-weight:bold;">&#93;</span> = o<span style="color:#006600; font-weight:bold;">&#91;</span>key<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">if</span> value.<span style="color:#9900CC;">blank</span>? <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> key != <span style="color:#996600;">'id'</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
    tmp.<span style="color:#9900CC;">freeze</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<div id="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://blog.smartlogicsolutions.com/2008/06/23/dont-abuse-the-session/" rel="bookmark" class="crp_title">Don&#8217;t Abuse the Session</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/09/10/using-activerecords-to_xml-to-produce-custom-xml-including-deep-level-associations/" rel="bookmark" class="crp_title">Using ActiveRecord&#8217;s to_xml to produce custom xml including deep level associations</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/07/21/advanced-model-based-searches-in-rails/" rel="bookmark" class="crp_title">Advanced Model Based searches in rails</a></li><li><a href="http://blog.smartlogicsolutions.com/2010/09/07/nicks-highlights-from-ruby-hoedown/" rel="bookmark" class="crp_title">Nick&#8217;s Highlights from Ruby Hoedown</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/07/11/losing-data-drag-and-drop-custom-class-flex-serialization/" rel="bookmark" class="crp_title">Losing Data When Drag and Dropping Custom Classes in Flex?</a></li><li>Powered by <a href="http://ajaydsouza.com/wordpress/plugins/contextual-related-posts/">Contextual Related Posts</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://blog.smartlogicsolutions.com/2008/07/10/merging-a-has_many-relationship-into-one-instance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reading and replacing text in Word DocX and Excel XlsX documents using Ruby</title>
		<link>http://blog.smartlogicsolutions.com/2008/07/09/reading-and-replacing-text-in-word-docx-and-excel-xlsx-documents-using-ruby/</link>
		<comments>http://blog.smartlogicsolutions.com/2008/07/09/reading-and-replacing-text-in-word-docx-and-excel-xlsx-documents-using-ruby/#comments</comments>
		<pubDate>Wed, 09 Jul 2008 22:37:43 +0000</pubDate>
		<dc:creator>Joseph Jakuta</dc:creator>
				<category><![CDATA[Excel]]></category>
		<category><![CDATA[Joseph Jakuta]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Word]]></category>

		<guid isPermaLink="false">http://blog.smartlogicsolutions.com/2008/07/09/reading-and-replacing-text-in-word-docx-and-excel-xlsx-documents-using-ruby/</guid>
		<description><![CDATA[So as you may know. The new Word and Excel formats are similar to open office document formats in that they are just zips of multiple xml documents (well mostly xml documents). So what we wanted to do for our project (the WebDav one mentioned in my last post) is to set up a simple [...]]]></description>
			<content:encoded><![CDATA[<p>So as you may know.  The new Word and Excel formats are similar to open office document formats in that they are just zips of multiple xml documents (well mostly xml documents).  So what we wanted to do for our project (the WebDav one mentioned in my last post) is to set up a simple templating system that would do variable replacement in Word/Excel documents. And it turned out to be a piece of cake.  I am just going to go through the DocX version of template model, but the only difference between them is the folder structure so there is not too much to change to get this working for both.</p>
<p><span id="more-57"></span></p>
<p>The basic model looks as follows.  make_temp is just a method that makes temp files/directories so you can set that up however you like.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> DocxTemplateTool <span style="color:#006600; font-weight:bold;">&lt;</span> TemplateTool
  <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'find'</span>
  <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'zip/zip'</span>
  <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'zip/zipfilesystem'</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>data<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@temp_path</span> = make_temp<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;.zip&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@temp_dir</span>  = make_temp
    <span style="color:#0066ff; font-weight:bold;">@data</span>      = data
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now we have can get started on reading the document and then replacing some text.  We will start with the shell of method and then add stuff.  In the beginning we need to save our data as a zip file (I should mention all of our data here is saved in blobs) and then unzip it&#8217;s contents in another directory.  After we are done, we of course want to clean up all of these temp files.  Both of the methods are going to be used by the replace method and by a validation method so to keep it DRY they are going into protected class methods.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> replace<span style="color:#006600; font-weight:bold;">&#40;</span>vars=<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    rdata = <span style="color:#0000FF; font-weight:bold;">nil</span>
    <span style="color:#9966CC; font-weight:bold;">begin</span>
      loadup
      <span style="color:#008000; font-style:italic;">#more code is going here</span>
    <span style="color:#9966CC; font-weight:bold;">ensure</span>
      cleanup
    <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#0000FF; font-weight:bold;">return</span> rdata
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  protected
  <span style="color:#9966CC; font-weight:bold;">def</span> loadup
      <span style="color:#CC00FF; font-weight:bold;">Dir</span>.<span style="color:#9900CC;">mkdir</span><span style="color:#006600; font-weight:bold;">&#40;</span>@temp_dir, <span style="color:#006666;">777</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>@temp_path, <span style="color:#996600;">'wb'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> f.<span style="color:#9900CC;">write</span> data <span style="color:#006600; font-weight:bold;">&#125;</span>
      args = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'unzip'</span>, <span style="color:#0066ff; font-weight:bold;">@temp_path</span>, <span style="color:#996600;">'-d'</span>, <span style="color:#0066ff; font-weight:bold;">@temp_dir</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#996600;">&quot;Could not unzip #{@temp_path}&quot;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#CC0066; font-weight:bold;">system</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
      args = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'chmod'</span>,<span style="color:#996600;">'-R'</span>,<span style="color:#996600;">'777'</span>, <span style="color:#0066ff; font-weight:bold;">@temp_dir</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#996600;">&quot;Could not chmod #{@temp_path}&quot;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#CC0066; font-weight:bold;">system</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> cleanup
      <span style="color:#CC00FF; font-weight:bold;">Dir</span>.<span style="color:#9900CC;">chdir</span><span style="color:#006600; font-weight:bold;">&#40;</span>RAILS_ROOT<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#CC00FF; font-weight:bold;">FileUtils</span>.<span style="color:#9900CC;">rm</span><span style="color:#006600; font-weight:bold;">&#40;</span>@temp_path<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">exists</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>@temp_path<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#CC00FF; font-weight:bold;">FileUtils</span>.<span style="color:#9900CC;">rm_rf</span><span style="color:#006600; font-weight:bold;">&#40;</span>@temp_dir<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">exists</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>@temp_dir<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>The only piece here that might not make sense is the need to call Dir.chdir(RAILS_ROOT) in cleanup.  The reason for this is that during the course of the replace method we may find ourselves in that directory and when we go to clean it up we won&#8217;t be able to delete it if we had <em>cd</em>&#8216;ed to it.</p>
<p>Before we go onto the replace method there is one more protected method that we are going to have to write.  This will method will check to make sure that as we are going through directories we are only doing replacement in the files we want to.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  protected
    <span style="color:#9966CC; font-weight:bold;">def</span> prunecheck?<span style="color:#006600; font-weight:bold;">&#40;</span>path<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#CC00FF; font-weight:bold;">FileTest</span>.<span style="color:#9900CC;">directory</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>path<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&amp;&amp;</span>
      path != <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span>@temp_dir<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&amp;&amp;</span>
      path != <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span>@temp_dir,<span style="color:#996600;">'word'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&amp;&amp;</span>
      path != <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span>@temp_dir,<span style="color:#996600;">'docProps'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>As you look through the file structure you will see that we are ignoring all of the _rels directories since their purpose is to tell word which files do what and we do not want to ruin that.  I also ignored the theme directory by my own choice, and we probably could choose to ignore other files n the word directory such as fontTable.xml, but as is this will allow you to replace anything in the document itself as well as in the metadata.</p>
<p>So finally we are going to do some replacement.  Follows is the code that goes in #more code is going here.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">      <span style="color:#CC00FF; font-weight:bold;">Find</span>.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span>@temp_dir<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>path<span style="color:#006600; font-weight:bold;">|</span>
        <span style="color:#CC00FF; font-weight:bold;">Find</span>.<span style="color:#9900CC;">prune</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>prunecheck?<span style="color:#006600; font-weight:bold;">&#40;</span>path<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#CC00FF; font-weight:bold;">FileTest</span>.<span style="color:#9900CC;">directory</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>path<span style="color:#006600; font-weight:bold;">&#41;</span>
          sdata = <span style="color:#0000FF; font-weight:bold;">nil</span>
          <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>path, <span style="color:#996600;">'r'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> sdata = f.<span style="color:#9900CC;">read</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
          <span style="color:#CC00FF; font-weight:bold;">FileUtils</span>.<span style="color:#9900CC;">rm</span><span style="color:#006600; font-weight:bold;">&#40;</span>path<span style="color:#006600; font-weight:bold;">&#41;</span>
          <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>path, <span style="color:#996600;">'w'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> f.<span style="color:#9900CC;">write</span> replace_data<span style="color:#006600; font-weight:bold;">&#40;</span>sdata,vars<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
      <span style="color:#CC00FF; font-weight:bold;">FileUtils</span>.<span style="color:#9900CC;">rm</span><span style="color:#006600; font-weight:bold;">&#40;</span>@temp_path<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">exists</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>@temp_path<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#CC00FF; font-weight:bold;">Dir</span>.<span style="color:#9900CC;">chdir</span><span style="color:#006600; font-weight:bold;">&#40;</span>@temp_dir<span style="color:#006600; font-weight:bold;">&#41;</span>
      args = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'zip'</span>, <span style="color:#996600;">'-r'</span>, <span style="color:#0066ff; font-weight:bold;">@temp_path</span>, <span style="color:#996600;">'*'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#996600;">&quot;Could not rezip file&quot;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#CC0066; font-weight:bold;">system</span><span style="color:#006600; font-weight:bold;">&#40;</span>args.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot; &quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>@temp_path, <span style="color:#996600;">'r'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> rdata = f.<span style="color:#9900CC;">read</span> <span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>We are beginning by using the Find.prune method to search through the directory structure for all files that we are going to be working on.  If we find a file the process is as follows.</p>
<p>  1. Read the data from the file into memory.<br />
  2. Remove the file.<br />
  3. Run a method on the data to do whatever replacements you would like and then save it back to where the file was before you deleted it.</p>
<p>I was not going to provide my replace_data method since it is particular to the project I wrote this for, but pretty much any sort of methods with gsub functions is what should be used.  Lets just say replace_data looks like this.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> replace_data<span style="color:#006600; font-weight:bold;">&#40;</span>data, vars<span style="color:#006600; font-weight:bold;">&#41;</span>
    data.<span style="color:#CC0066; font-weight:bold;">gsub</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>PHP<span style="color:#006600; font-weight:bold;">/</span>, <span style="color:#996600;">'Ruby'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>After the files have been replaced  we are going to <em>cd</em> to the temp directory and rezip it.  I chose to use a UNIX system call here since there were issues using Ruby&#8217;s zip class (if I recall correctly it was adding an extra folder when it was rezipping it).  After that just, reread the zip file so that you can return that data after you are done cleaning up and voila you have a Word Document that doesn&#8217;t have any mention of PHP!</p>
<p>One final method we are going to add before we are done.  It is very likely that you are going to want to make sure someone didn&#8217;t put anything malicious in the file that is going to mess with your system or maybe just let the user know why some text isn&#8217;t getting replaced.  For that we have this method.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> validate_data
    docx_errors = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#9966CC; font-weight:bold;">begin</span>
      loadup
      <span style="color:#CC00FF; font-weight:bold;">Find</span>.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span>@temp_dir<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>path<span style="color:#006600; font-weight:bold;">|</span>
        <span style="color:#CC00FF; font-weight:bold;">Find</span>.<span style="color:#9900CC;">prune</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>prunecheck?<span style="color:#006600; font-weight:bold;">&#40;</span>path<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>path, <span style="color:#996600;">'r'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> docx_errors.<span style="color:#9900CC;">concat</span><span style="color:#006600; font-weight:bold;">&#40;</span>validate_template<span style="color:#006600; font-weight:bold;">&#40;</span>f.<span style="color:#9900CC;">read</span> <span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#CC00FF; font-weight:bold;">FileTest</span>.<span style="color:#9900CC;">directory</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>path<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">ensure</span>
      cleanup
    <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#0000FF; font-weight:bold;">return</span> docx_errors
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>It pretty much goes through the document just like we did with the replacement except we will call a method validate_template (that you will have to write) that will make sure your data is AOK!</p>
<div id="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://blog.smartlogicsolutions.com/2008/07/01/microsoft-webdav-opens-document-as-read-only-when-using-railsdav/" rel="bookmark" class="crp_title">Microsoft WebDav opens document as Read-Only when using RailsDav</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/07/21/adobe-pdfs-and-table-of-contents-on-the-fly/" rel="bookmark" class="crp_title">Merging Adobe PDF&#8217;s and generating a table of contents on the fly using ruby</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/08/04/introducing-environmentalize-an-intuitive-environment-focused-config-structure-for-your-rails-applications/" rel="bookmark" class="crp_title">Introducing environmentalist: an intuitive, environment-focused config structure for your rails applications</a></li><li><a href="http://blog.smartlogicsolutions.com/2010/05/13/directory-conventions-for-rack-middleware-rubygems/" rel="bookmark" class="crp_title">Directory Conventions for Rack Middleware RubyGems</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/06/02/better-setup-for-environments-in-rails/" rel="bookmark" class="crp_title">Better setup for environments in Rails</a></li><li>Powered by <a href="http://ajaydsouza.com/wordpress/plugins/contextual-related-posts/">Contextual Related Posts</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://blog.smartlogicsolutions.com/2008/07/09/reading-and-replacing-text-in-word-docx-and-excel-xlsx-documents-using-ruby/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Microsoft WebDav opens document as Read-Only when using RailsDav</title>
		<link>http://blog.smartlogicsolutions.com/2008/07/01/microsoft-webdav-opens-document-as-read-only-when-using-railsdav/</link>
		<comments>http://blog.smartlogicsolutions.com/2008/07/01/microsoft-webdav-opens-document-as-read-only-when-using-railsdav/#comments</comments>
		<pubDate>Tue, 01 Jul 2008 20:49:55 +0000</pubDate>
		<dc:creator>Joseph Jakuta</dc:creator>
				<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[Joseph Jakuta]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[WebDav]]></category>

		<guid isPermaLink="false">http://blog.smartlogicsolutions.com/2008/07/01/microsoft-webdav-opens-document-as-read-only-when-using-railsdav/</guid>
		<description><![CDATA[I had been working on a project in which we wanted to utilize WebDAV (namely for editing Word &#038; Excel  Documents that were saved in our application).  In order to do this we decided to use a plugin from <a href="http://liverail.net" target="_new">liverail.net</a> that can be found <a href="http://www.liverail.net/articles/2006/06/25/webdav-ruby-on-rails-plugin" target="_new">here</a>.  It was pretty easy to hook up after a little direction from a guy over at Benryan Inc [apologies I cannot find a link for them], but there was a major issue. When opening a document through the ActiveX controller for editing it was opening in Read-Only mode.  

After a few starts and stops, many hours of reading through the <a href="http://www.webdav.org/" target="_new">webdav documentation</a>, and browsing through the http traffic using <a href="http://www.fiddlertool.com/fiddler/" target="_new">Fiddler</a> - it was determined that locking was the issue.]]></description>
			<content:encoded><![CDATA[<p>I had been working on a project in which we wanted to utilize WebDAV (namely for editing Word &#038; Excel  Documents that were saved in our application).  In order to do this we decided to use a plugin from <a href="http://liverail.net" target="_new">liverail.net</a> that can be found <a href="http://www.liverail.net/articles/2006/06/25/webdav-ruby-on-rails-plugin" target="_new">here</a>.  It was pretty easy to hook up after a little direction from a guy over at Benryan Inc [apologies I cannot find a link for them], but there was a major issue. When opening a document through the ActiveX controller for editing it was opening in Read-Only mode.  </p>
<p>After a few starts and stops, many hours of reading through the <a href="http://www.webdav.org/" target="_new">webdav documentation</a>, and browsing through the http traffic using <a href="http://www.fiddlertool.com/fiddler/" target="_new">Fiddler</a> &#8211; it was determined that locking was the issue.</p>
<p><span id="more-54"></span></p>
<p>What I found in the RailsDav plugin is that the implementation of locking is as follows (lines 92-100 of railsdav/act_as_railsdav.rb):</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> webdav_lock<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#008000; font-style:italic;">#TODO implementation for now return a 200 OK</span>
    render <span style="color:#ff3333; font-weight:bold;">:nothing</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>, <span style="color:#ff3333; font-weight:bold;">:status</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">200</span> <span style="color:#9966CC; font-weight:bold;">and</span> <span style="color:#0000FF; font-weight:bold;">return</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> webdav_unlock<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#008000; font-style:italic;">#TODO implementation for now return a 200 OK</span>
    render <span style="color:#ff3333; font-weight:bold;">:nothing</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>, <span style="color:#ff3333; font-weight:bold;">:status</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">200</span> <span style="color:#9966CC; font-weight:bold;">and</span> <span style="color:#0000FF; font-weight:bold;">return</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>However, Microsoft actually won&#8217;t let you edit a document with such lax locking.  So I rewrote the lock method so that it returned a valid lock.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> webdav_lock<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
     <span style="color:#0066ff; font-weight:bold;">@lock</span> = get_lock<span style="color:#006600; font-weight:bold;">&#40;</span>@path_info<span style="color:#006600; font-weight:bold;">&#41;</span>
     <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@lock</span>
         response.<span style="color:#9900CC;">headers</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;Lock-Token&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;&lt;#{@lock.token}&gt;&quot;</span>
         response.<span style="color:#9900CC;">headers</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;Content-Type&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">'text/xml; charset=&quot;utf-8&quot;'</span>
         render <span style="color:#ff3333; font-weight:bold;">:inline</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9966CC; font-weight:bold;">class</span>.<span style="color:#9900CC;">lock_xml</span>, <span style="color:#ff3333; font-weight:bold;">:layout</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">false</span>, <span style="color:#ff3333; font-weight:bold;">:type</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:rxml</span>, <span style="color:#ff3333; font-weight:bold;">:status</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">200</span>  <span style="color:#9966CC; font-weight:bold;">and</span> <span style="color:#0000FF; font-weight:bold;">return</span>
       <span style="color:#9966CC; font-weight:bold;">else</span>
         render  <span style="color:#ff3333; font-weight:bold;">:nothing</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>, <span style="color:#ff3333; font-weight:bold;">:status</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#6666ff; font-weight:bold;">WebDavErrors::ForbiddenError</span> <span style="color:#9966CC; font-weight:bold;">and</span> <span style="color:#0000FF; font-weight:bold;">return</span>
       <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>There were a few other pieces of code that were needed to get this working though.  Namely the .lock_xml method, and get_lock.  Let&#8217;s tackle them each in turn.</p>
<p>In railsdav/propxml.rb you can find the XML structures for the PROPFIND and the PROPPATCH methods for WebDAV.  However both locking and unlocking require their own structures.  So I added one for locking.  It is as follows:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> lock_xml
<span style="color:#006600; font-weight:bold;">&lt;&amp;</span>lt;EOPROPFIND_XML 
         xml.<span style="color:#9900CC;">D</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:multistatus</span>, <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#996600;">&quot;xmlns:D&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;DAV:&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
           xml.<span style="color:#9900CC;">D</span> <span style="color:#ff3333; font-weight:bold;">:lockdiscovery</span> <span style="color:#9966CC; font-weight:bold;">do</span>
             xml.<span style="color:#9900CC;">D</span> <span style="color:#ff3333; font-weight:bold;">:activelock</span> <span style="color:#9966CC; font-weight:bold;">do</span>
               xml.<span style="color:#9900CC;">D</span> <span style="color:#ff3333; font-weight:bold;">:locktype</span> <span style="color:#9966CC; font-weight:bold;">do</span> 
                 xml.<span style="color:#9900CC;">D</span> <span style="color:#0066ff; font-weight:bold;">@lock</span>.<span style="color:#9900CC;">type</span>.<span style="color:#9900CC;">to_sym</span>
               <span style="color:#9966CC; font-weight:bold;">end</span>
               xml.<span style="color:#9900CC;">D</span> <span style="color:#ff3333; font-weight:bold;">:lockscope</span> <span style="color:#9966CC; font-weight:bold;">do</span> 
                 xml.<span style="color:#9900CC;">D</span> <span style="color:#0066ff; font-weight:bold;">@lock</span>.<span style="color:#9900CC;">scope</span>.<span style="color:#9900CC;">to_sym</span>
               <span style="color:#9966CC; font-weight:bold;">end</span>
               xml.<span style="color:#9900CC;">D</span> <span style="color:#ff3333; font-weight:bold;">:depth</span>, <span style="color:#0066ff; font-weight:bold;">@lock</span>.<span style="color:#9900CC;">depth</span>
               xml.<span style="color:#9900CC;">D</span> <span style="color:#ff3333; font-weight:bold;">:timeout</span>, <span style="color:#0066ff; font-weight:bold;">@lock</span>.<span style="color:#9900CC;">timeout_full</span>               
               xml.<span style="color:#9900CC;">D</span> <span style="color:#ff3333; font-weight:bold;">:locktoken</span> <span style="color:#9966CC; font-weight:bold;">do</span> 
                 xml.<span style="color:#9900CC;">D</span> <span style="color:#ff3333; font-weight:bold;">:href</span>, <span style="color:#0066ff; font-weight:bold;">@lock</span>.<span style="color:#9900CC;">token</span>
               <span style="color:#9966CC; font-weight:bold;">end</span>               
               xml.<span style="color:#9900CC;">D</span> <span style="color:#ff3333; font-weight:bold;">:lockroot</span> <span style="color:#9966CC; font-weight:bold;">do</span> 
                 xml.<span style="color:#9900CC;">D</span> <span style="color:#ff3333; font-weight:bold;">:href</span>, <span style="color:#0066ff; font-weight:bold;">@lock</span>.<span style="color:#9900CC;">href</span>
               <span style="color:#9966CC; font-weight:bold;">end</span>
             <span style="color:#9966CC; font-weight:bold;">end</span>
           <span style="color:#9966CC; font-weight:bold;">end</span>
         <span style="color:#9966CC; font-weight:bold;">end</span>  
EOPROPFIND_XML
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Then there is the get_lock method.  Writing get_lock was a two step process.  If you look at (lines 269-287 of railsdav/act_as_railsdav.rb) you can see several methods that are very similar in function to their respective purposes.  So I began by simply adding the following in this section:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> get_lock<span style="color:#006600; font-weight:bold;">&#40;</span>path<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#6666ff; font-weight:bold;">WebDavErrors::ForbiddenError</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Then in my application&#8217;s controller that overrides all of the acts_as_railsdav methods I did just that:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> get_lock<span style="color:#006600; font-weight:bold;">&#40;</span>path<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#0000FF; font-weight:bold;">false</span> <span style="color:#9966CC; font-weight:bold;">unless</span> get_resource_for_path<span style="color:#006600; font-weight:bold;">&#40;</span>path<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">locked</span>?
    <span style="color:#0000FF; font-weight:bold;">return</span> ActiveRecordLock.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#123;</span>:type <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'write'</span>, <span style="color:#ff3333; font-weight:bold;">:scope</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'exclusive'</span>, <span style="color:#ff3333; font-weight:bold;">:timeout</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">60</span><span style="color:#006600; font-weight:bold;">*</span><span style="color:#006666;">60</span><span style="color:#006600; font-weight:bold;">*</span><span style="color:#006666;">5</span>, <span style="color:#ff3333; font-weight:bold;">:href</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> path, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span><span style="color:#006666;">4</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>So now you&#8217;ll notice two new things that need coding here.  The .locked? method for the resource and ActiveRecordLock.  We decided to not worry about multiple users editing the same document at the same time on this project.  Because of this and the time constraints .locked? simply returns true.  If one were to deal with unlocking at some point this would have to be come a check to the database or something to make sure that the document is indeed unlocked.  The same goes for ActiveRecordLock.  It really just deals with the flat information needed by the Lock XML and not saving it to check if it is locked later on.  Maybe someday, somebody will undertake that task I suppose.  Anyway, here is what I had for the portion of the ActiveRecordLock model that I needed.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> ActiveRecordLock
   attr_accessor <span style="color:#ff3333; font-weight:bold;">:type</span>, <span style="color:#ff3333; font-weight:bold;">:scope</span>, <span style="color:#ff3333; font-weight:bold;">:timeout</span>, <span style="color:#ff3333; font-weight:bold;">:depth</span>, <span style="color:#ff3333; font-weight:bold;">:timeout_units</span>, <span style="color:#ff3333; font-weight:bold;">:href</span>, <span style="color:#ff3333; font-weight:bold;">:token</span>
&nbsp;
   <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>      
      <span style="color:#0066ff; font-weight:bold;">@type</span>    = args<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:type</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#0066ff; font-weight:bold;">@scope</span>   = args<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:scope</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#0066ff; font-weight:bold;">@timeout</span> = args<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:timeout</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#0066ff; font-weight:bold;">@href</span>    = args<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:href</span><span style="color:#006600; font-weight:bold;">&#93;</span>  
      <span style="color:#0066ff; font-weight:bold;">@depth</span>   = <span style="color:#996600;">'Infinity'</span>
      <span style="color:#0066ff; font-weight:bold;">@timeout_units</span> = <span style="color:#996600;">'Second'</span>
      <span style="color:#0066ff; font-weight:bold;">@token</span>   = build_token<span style="color:#006600; font-weight:bold;">&#40;</span>args<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:id</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
   <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
   <span style="color:#9966CC; font-weight:bold;">def</span> timeout_full
     <span style="color:#996600;">&quot;#{self.timeout_units}-#{self.timeout}&quot;</span>
   <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
   protected
     <span style="color:#9966CC; font-weight:bold;">def</span> build_token<span style="color:#006600; font-weight:bold;">&#40;</span>text<span style="color:#006600; font-weight:bold;">&#41;</span>
       <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'digest/md5'</span>
       md5 = <span style="color:#6666ff; font-weight:bold;">Digest::MD5</span>.<span style="color:#9900CC;">hexdigest</span><span style="color:#006600; font-weight:bold;">&#40;</span>text.<span style="color:#9900CC;">to_s</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_s</span>
       <span style="color:#996600;">'opaquelocktoken:'</span><span style="color:#006600; font-weight:bold;">+</span>md5<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span>,<span style="color:#006666;">7</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">+</span><span style="color:#996600;">'-'</span><span style="color:#006600; font-weight:bold;">+</span>md5<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">8</span>,<span style="color:#006666;">11</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">+</span><span style="color:#996600;">'-'</span><span style="color:#006600; font-weight:bold;">+</span>md5<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">12</span>,<span style="color:#006666;">15</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">+</span><span style="color:#996600;">'-'</span><span style="color:#006600; font-weight:bold;">+</span>md5<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">16</span>,<span style="color:#006666;">19</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">+</span><span style="color:#996600;">'-'</span><span style="color:#006600; font-weight:bold;">+</span>md5<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">20</span>,<span style="color:#006666;">31</span><span style="color:#006600; font-weight:bold;">&#93;</span>
     <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>There is still plenty that needs to be done to get the full lock/unlock, but hopefully this will get someone started and save a few headaches.  </p>
<div id="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://blog.smartlogicsolutions.com/2008/07/09/reading-and-replacing-text-in-word-docx-and-excel-xlsx-documents-using-ruby/" rel="bookmark" class="crp_title">Reading and replacing text in Word DocX and Excel XlsX documents using Ruby</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/10/10/making-willpaginate-and-rails-to_xml-play-nice-with-activeresource/" rel="bookmark" class="crp_title">Making WillPaginate and Rails to_xml play nice with ActiveResource</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/09/10/using-activerecords-to_xml-to-produce-custom-xml-including-deep-level-associations/" rel="bookmark" class="crp_title">Using ActiveRecord&#8217;s to_xml to produce custom xml including deep level associations</a></li><li><a href="http://blog.smartlogicsolutions.com/2009/10/23/dry-up-your-controllers-with-find_or_redirect/" rel="bookmark" class="crp_title">DRY up your Controllers with find_or_redirect</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/07/21/advanced-model-based-searches-in-rails/" rel="bookmark" class="crp_title">Advanced Model Based searches in rails</a></li><li>Powered by <a href="http://ajaydsouza.com/wordpress/plugins/contextual-related-posts/">Contextual Related Posts</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://blog.smartlogicsolutions.com/2008/07/01/microsoft-webdav-opens-document-as-read-only-when-using-railsdav/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SLS Welcomes Joseph Jakuta</title>
		<link>http://blog.smartlogicsolutions.com/2007/05/16/sls-welcomes-joseph-jakuta/</link>
		<comments>http://blog.smartlogicsolutions.com/2007/05/16/sls-welcomes-joseph-jakuta/#comments</comments>
		<pubDate>Wed, 16 May 2007 17:52:26 +0000</pubDate>
		<dc:creator>Yair Flicker</dc:creator>
				<category><![CDATA[Company News]]></category>
		<category><![CDATA[Joseph Jakuta]]></category>
		<category><![CDATA[New Hires]]></category>

		<guid isPermaLink="false">http://blog.smartlogicsolutions.com/2007/05/16/sls-welcomes-joseph-jakuta/</guid>
		<description><![CDATA[SmartLogic Solutions welcomes Joseph Jakuta to the team. Joseph bring many years&#8217; experience in software programming to the company. Joseph&#8217;s first task will be to learn Ruby on Rails in an effort to continue to build our company&#8217;s proficiency in RoR. Joseph spent the last few years working for the Democratic Congressional Campaign Committee. Related [...]]]></description>
			<content:encoded><![CDATA[<p>SmartLogic Solutions welcomes <a href="http://www.smartlogicsolutions.com/wiki/Joseph_Jakuta">Joseph Jakuta</a> to the team.  Joseph bring many years&#8217; experience in software programming to the company.  Joseph&#8217;s first task will be to learn Ruby on Rails in an effort to continue to build our company&#8217;s proficiency in RoR.  Joseph spent the last few years working for the <a href="http://www.dccc.org/">Democratic Congressional Campaign Committee</a>.</p>
<div id="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://blog.smartlogicsolutions.com/2007/05/10/happy-birthday-smartlogic-solutions/" rel="bookmark" class="crp_title">Happy Birthday SmartLogic Solutions!</a></li><li><a href="http://blog.smartlogicsolutions.com/2007/05/07/sls-welcomes-scott-davis-to-the-team/" rel="bookmark" class="crp_title">SLS Welcomes Scott Davis to the Team</a></li><li><a href="http://blog.smartlogicsolutions.com/2007/03/01/introducing-smartlogic-solutions-blog/" rel="bookmark" class="crp_title">Introducing the SmartLogic Solutions Blog</a></li><li><a href="http://blog.smartlogicsolutions.com/2009/02/16/tatft-test-private-methods-in-c/" rel="bookmark" class="crp_title">TATFT: Test Private Methods in C++</a></li><li><a href="http://blog.smartlogicsolutions.com/2007/05/14/dual-20-lcds-new-computers/" rel="bookmark" class="crp_title">Dual 20&#8243; LCD&#8217;s, New Computers</a></li><li>Powered by <a href="http://ajaydsouza.com/wordpress/plugins/contextual-related-posts/">Contextual Related Posts</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://blog.smartlogicsolutions.com/2007/05/16/sls-welcomes-joseph-jakuta/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

