<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 14 May 2014 08:49, Andrew Stewart <span dir="ltr"><<a href="mailto:boss@airbladesoftware.com" target="_blank">boss@airbladesoftware.com</a>></span> wrote:</div>
<div class="gmail_quote"><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">I'm sure this is trivial with the correct approach. </blockquote>
<div><br></div><div><br></div><div>Hint: it confuses the heck out of most postgrads in Computer Science departments, so, yeah, not quite...</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
- In 2006 before SASS etc existed, I wrote a Rails plugin for nested CSS. It read a nested stylesheet and flattened it into normal CSS. Back then I wasn't sure how to parse a nested stylesheet...and I still don't know how. (Stop laughing at the back!)<br>
</blockquote><div><br></div><div><br></div><div>That use case sounds almost perfect for using a PEG as a starting point (as already pointed out). Start here:</div><div><br></div><div><a href="http://www.rubyinside.com/writing-parsers-in-ruby-using-treetop-3911.html">http://www.rubyinside.com/writing-parsers-in-ruby-using-treetop-3911.html</a></div>
<div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">- A few months ago I needed to convert hospital admissions records from a PDF to CSV. Each record had fields like id, name, various dates, clinical history, attending doctor, etc. The fields weren't always in the same order due to the layout of text in the PDF, and some fields were optional. Sometimes there were several fields on a line, and a field could be spread over several lines. I did my usual thing of looping over each line, matching field names with regular expressions, and trying to keep track of where I was with a state variable. Its sole virtue was that it (sort of) worked; otherwise it was horrible: hard to understand, hard to modify, hard to extend, and very hard to debug.<br>
</blockquote><div><br></div><div><br></div><div>Short version: go and read <i>Metaprogramming in Ruby</i> and you will immediately see how to do this using #send and #method_missing in a much more elegant way. </div><div>
<br></div><div>Long version: I actually think every Ruby coder should read that book because then you understand what your code is actually doing, rather than just saying "well, this is how I used to do it in [perl/python/bash/php/java/whatever]" and producing huge procedural blobs of unmaintainable mess. It's my favourite Ruby book by some margin.</div>
<div><br></div><div>In this use case, let's assume you have a PatientRecord object with some accessors defined:</div><div><br></div><div>class PatientRecord</div><div> attr_accessor :id, :name, :date, [...]</div><div>
end<br></div><div><br></div><div>I can write a loop over the process that assuming @current_page has an array of attribute hashes that look like {:name => "id", :value => 12345} I can just write this:</div>
<div><br></div><div>@record = Record.new</div><div>@current_page.attributes.each{|attribute| @record.send("#{attribute[:name]}=", attribute[:value]) }</div><div>puts @record.inspect # => {:id => 12345, :name => "John Smith", :date => 2013-12-25 [...] }</div>
<div><br></div><div>No state. No ifs or case statements. The entire parsing (excluding setting up the data into a sort-of-consistent format), is one line.</div><div><br></div><div>That's the tip of the iceberg of what you can do with a smidge more knowledge of how to metacode. The next step would be to allow method_missing to do some work if needed, and to be able to create related objects (like Doctors and so on). YMMV, but to my mind it's worth learning, especially for this sort of coding problem.</div>
<div><br></div></div></div></div>