<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5548895711100825622</id><updated>2025-06-29T16:38:02.578-04:00</updated><category term="rails"/><category term="ruby"/><category term="rspec"/><category term="checklists"/><category term="launch"/><category term="heroku"/><category term="css"/><category term="stand-up"/><category term="active-record"/><category term="agile"/><category term="rails-3.0"/><category term="application development"/><category term="cucumber"/><category term="customer-centered web design"/><category term="developer-challenge"/><category term="git"/><category term="jquery"/><category term="personas"/><category term="presentations"/><category term="radiant"/><category term="testing"/><category term="associations"/><category term="content management systems"/><category term="fundamentals"/><category term="html"/><category term="meta-programming"/><category term="named scopes"/><category term="redmine"/><category term="vim"/><category term="blank-static"/><category term="bourne"/><category term="centos"/><category term="compass"/><category term="gems"/><category term="internet-explorer"/><category term="life hacks"/><category term="mocha"/><category term="object-design"/><category term="osx"/><category term="railsconf"/><category term="sass"/><category term="saving"/><category term="spree"/><category term="static-matic"/><category term="unix"/><category term="workflow"/><category term="application-architecture"/><category term="ask for help"/><category term="bundler"/><category term="business"/><category term="capistrano"/><category term="capybara"/><category term="craftmanship"/><category term="cufon"/><category term="domain-modelling"/><category term="domain-patterns"/><category term="ebooks"/><category term="elixir"/><category term="ember.js"/><category term="error-handling"/><category term="errors"/><category term="facebook"/><category term="google-site-search"/><category term="haml"/><category term="html-5"/><category term="i18n"/><category term="interview"/><category term="javascript"/><category term="maintenance"/><category term="memcached"/><category term="memory-consumption"/><category term="mocks"/><category term="monitoring"/><category term="mysql"/><category term="optimization"/><category term="productivity"/><category term="rails-3.2"/><category term="rake"/><category term="rdoc"/><category term="refinery"/><category term="rest"/><category term="rmagick"/><category term="rvm"/><category term="s3"/><category term="safari"/><category term="searchlogic"/><category term="sftp"/><category term="shopify"/><category term="spork"/><category term="sql"/><category term="strategy"/><category term="templates"/><category term="textmate"/><category term="tools"/><category term="uploads"/><category term="usability"/><category term="user-stories"/><category term="validations"/><category term="web design"/><title type='text'>Firsthand Web Development, Ruby on Rails, Montréal</title><subtitle type='html'>All things Ruby on Rails, Content Management Systems and Web Development</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.firsthand.ca/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>156</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-7573863325104662796</id><published>2015-12-11T15:43:00.004-05:00</published><updated>2015-12-11T15:43:40.027-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="elixir"/><category scheme="http://www.blogger.com/atom/ns#" term="presentations"/><title type='text'>How Elixir is Transforming My Mind</title><content type='html'>&lt;p&gt;Last month I presented a talk to &lt;a href=&quot;http://www.montrealrb.com/&quot;&gt;Montreal.rb&lt;/a&gt; on Elixir - a language I have been exploring on and off over the last year. Like any good talk from a newbie, it contains bloopers, mis-information and whole lot of gusto. Watch it at your peril!&lt;/p&gt;

&lt;h2&gt;Video&lt;/h2&gt;

&lt;iframe src=&quot;https://player.vimeo.com/video/148664265&quot; width=&quot;500&quot; height=&quot;313&quot; frameborder=&quot;0&quot; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;/iframe&gt; &lt;p&gt;&lt;a href=&quot;https://vimeo.com/148664265&quot;&gt;How Elixir is Transforming My Mind&lt;/a&gt; from &lt;a href=&quot;https://vimeo.com/firsthand&quot;&gt;Nicholas Henry&lt;/a&gt; on &lt;a href=&quot;https://vimeo.com&quot;&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;

&lt;br/&gt;
&lt;h2&gt;Slides&lt;/h2&gt;

&lt;script async class=&quot;speakerdeck-embed&quot; data-id=&quot;07c337ab09d9412ca7574207d47fb630&quot; data-ratio=&quot;1.77777777777778&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/7573863325104662796'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/7573863325104662796'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2015/12/how-elixir-is-transforming-my-mind.html' title='How Elixir is Transforming My Mind'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-2637658872947226399</id><published>2015-09-05T15:46:00.000-04:00</published><updated>2015-09-05T15:46:23.191-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="launch"/><title type='text'>Recently Launched: Wardware 2.0</title><content type='html'>&lt;p&gt;Over the last year I have had the pleasure to work with &lt;a href=&quot;http://www.airslie.com&quot;&gt;Airslie Ltd&lt;/a&gt;, a UK-based medical informatics company, and &lt;a href=&quot;https://www.kch.nhs.uk/&quot;&gt;King&amp;#39;s College Hospital (NHS Foundation Trust)&lt;/a&gt; to rewrite and extended their clinical observations and assessments system, Wardware®. Wardware enables the entry, analysis and display of &lt;strong&gt;Early Warning Scores&lt;/strong&gt; and other patient datasets for clinical use locally or remotely on &lt;strong&gt;mobile and desktop computers&lt;/strong&gt;. The application was originally built using PHP, sans framework, and the company who originally authored the application, Airslie, was motivated to rewrite it using an application framework. Their chosen framework was &lt;strong&gt;Ruby on Rails&lt;/strong&gt; and they approached me to lead the development effort.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;http://firsthand-blog.s3.amazonaws.com/2015/07/wardware-comparison.png&quot; alt=&quot;Mobile Desktop&quot;&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;Desktop and Mobile views of Patient Chart&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;facilitating-the-national-early-warning-score-(news)&quot;&gt;Facilitating the National Early Warning Score (NEWS)&lt;/h2&gt;
&lt;p&gt;The pivotal component of Wardware is the &lt;strong&gt;Observations and Assessments module&lt;/strong&gt;. This module implements a number of assessments, including a key assessment for patient health, the - &lt;a href=&quot;http://en.wikipedia.org/wiki/Early_warning_score#National_Early_Warning_Score.2C_UK&quot;&gt;National Early Warning Score&lt;/a&gt; (NEWS). &lt;a href=&quot;http://en.wikipedia.org/wiki/Early_warning_score&quot;&gt;Early Warning Scores&lt;/a&gt; (EWS) are used to &amp;quot;quickly determine the degree of illness of a patient&amp;quot;. This is determined by the scoring of physiological parameters such as temperature, heart rate and blood pressure. The total score assigns a patient to a risk category and the appropriate response, based on a predefined protocol, is carried out.&lt;/p&gt;&lt;p&gt;Physiological parameters are recorded using a mobile device, the &lt;a href=&quot;http://miocare.mio.com/global/product_A105_enUSA.asp&quot;&gt;MioCare Tablet&lt;/a&gt;, at the patient&amp;#39;s bedside. The patient&amp;#39;s charts, such as the NEWS chart can be viewed either on a desktop or the mobile device. The application has been developed using a &lt;a href=&quot;http://en.wikipedia.org/wiki/Responsive_web_design&quot;&gt;Responsive&lt;/a&gt; front-end framework, allowing a single UI to be used for both desktop and mobile devices.&lt;/p&gt;
&lt;h2 id=&quot;an-extendible-platform-for-supporting-different-assessments&quot;&gt;An extendible platform for supporting different assessments&lt;/h2&gt;
&lt;p&gt;The &lt;strong&gt;Observations and Assessments module&lt;/strong&gt; is designed to be extended. It is a platform for implementing other assessments by simply configuring the physiological parameters and the assessment&amp;#39;s calculator. Beyond NEWS, the Wardware installation at King&amp;#39;s College Hospital is currently configured for:&lt;/p&gt;&lt;ul id=&#39;draft_check_box_list_0&#39; &gt;&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Glasgow_Coma_Scale&quot;&gt;Glasgow Comma Scale&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Gastro-intestinal/Stools&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Body_mass_index&quot;&gt;Body Mass Index&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;key-assessments-summarized-in-configurable-wardboards-and-charts&quot;&gt;Key assessments summarized in configurable Wardboards and Charts&lt;/h2&gt;
&lt;p&gt;Key assessments scores for patients such as NEWS along with assessment frequencies and due times are summarized on the Wardboard.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;http://firsthand-blog.s3.amazonaws.com/2015/07/wardware-wardboard.png&quot; alt=&quot;wardboard&quot;&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;Wardboard summarizing current admissions for a specific ward.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Assessments with a specific threshold (e.g. a NEWS score greater than two) are also summarized at a ward and site-wide level.&lt;/p&gt;&lt;p&gt;Observation and Assessment Charts are presented in three formats:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1. Graphical&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;http://firsthand-blog.s3.amazonaws.com/2015/07/wardware-chart.png&quot; alt=&quot;graphical&quot;&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2. Tabular with the most &lt;em&gt;recent&lt;/em&gt; 20 observations&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;http://firsthand-blog.s3.amazonaws.com/2015/07/wardware-recent.png&quot; alt=&quot;graphical&quot;&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;3. Tabular with all &lt;em&gt;historical&lt;/em&gt; patient data paginated&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;http://firsthand-blog.s3.amazonaws.com/2015/07/wardware-historical.png&quot; alt=&quot;graphical&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-range-of-modules-supporting-a-patient&amp;#39;s-tracking-and-analysis-requirements&quot;&gt;A range of modules supporting a patient&amp;#39;s tracking and analysis requirements&lt;/h2&gt;
&lt;p&gt;Wardware doesn&amp;#39;t just support observations and assessments, it supports various tracking and analysis requirements to monitor a patient. Briefly these include:&lt;/p&gt;&lt;ul id=&#39;draft_check_box_list_1&#39; &gt;&lt;li&gt;&lt;strong&gt;Oxygen Delivery Management&lt;/strong&gt;, including the tracking of patient oxygen concentration targets&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Response Management&lt;/strong&gt;, recording responses to assessments such as NEWS&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Device Management&lt;/strong&gt; for surgical and urinary devices. Device Management tracks insertion and removal of devices for a patient, including the recording of complications&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Diarrhoea Management&lt;/strong&gt; integrated with Stools based on the Bristol Stool type&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Blood Products Management&lt;/strong&gt; (e.g. RBC, FFP, Platelets)&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Fluid Management&lt;/strong&gt; tracking patient&amp;#39;s fluid balance and reporting&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;integrated-admission-management-with-the-hospital&amp;#39;s-patient-information-management-system&quot;&gt;Integrated admission management with the hospital&amp;#39;s Patient Information Management System&lt;/h2&gt;
&lt;p&gt;Wardware&amp;#39;s Admissions module completes the admission process by assigning patients to a bed in their designated ward. Admissions for wards are automatically populated through a custom module integrating Wardware with KCH&amp;#39;s Patient Information Management System (PIMS) using the &lt;a href=&quot;http://en.wikipedia.org/wiki/Health_Level_7&quot;&gt;Health Level-7 (HL7)&lt;/a&gt; messaging format, &amp;quot;a set of international standards for transfer of clinical and administrative data between software applications&amp;quot;.&lt;/p&gt;
&lt;h2 id=&quot;and-there&amp;#39;s-a-lot-more&quot;&gt;And there&amp;#39;s a lot more&lt;/h2&gt;
&lt;p&gt;There is a lot more detail I can go into, but this post is long enough. Here are some facets that I&amp;#39;ll highlight here:&lt;/p&gt;&lt;ul id=&#39;draft_check_box_list_2&#39; &gt;&lt;li&gt;Authentication and Authorization Management&lt;/li&gt;&lt;li&gt;Patient search via bar code scan from admission bracelet&lt;/li&gt;&lt;li&gt;Business Continuity Programme (offline storage of patient obs)&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;domain-modeling-challenges&quot;&gt;Domain Modeling Challenges&lt;/h2&gt;
&lt;p&gt;In future blog posts I will discuss some of the interesting domain modelling challenges of this project and how I leveraged Martin Fowler&amp;#39;s &lt;a href=&quot;http://martinfowler.com/books/ap.html&quot;&gt;Analysis Patterns&lt;/a&gt;. His patterns for observations and measurements is based on his work with the &lt;a href=&quot;http://rewrite.rickbradley.com/articles/2006/07/06/cosmos-documentation/&quot;&gt;Cosmos Clinical Process Model for the UK National Health Service&lt;/a&gt;.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/2637658872947226399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/2637658872947226399'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2015/09/recently-launched-wardware-20.html' title='Recently Launched: Wardware 2.0'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-2637702661837411728</id><published>2015-05-28T08:49:00.000-04:00</published><updated>2015-06-01T08:41:30.897-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="object-design"/><title type='text'>Learning OO Design through Design Patterns</title><content type='html'>&lt;p&gt;Last week at &lt;a href=&quot;http://www.montrealrb.com&quot;&gt;Montreal.rb&lt;/a&gt; there was an open discussion on &lt;a href=&quot;http://railsconf.com/&quot;&gt;RailsConf&lt;/a&gt; held in Atlanta which I had attended this year. We discussed favorite talks, themes and general experiences. I prepared a few notes prompting folks to explore design patterns after seeing Sandi Metz&amp;#39;s talk, &lt;a href=&quot;http://confreaks.tv/videos/railsconf2015-nothing-is-something&quot;&gt;Nothing is Something&lt;/a&gt;. Why?&lt;/p&gt;
&lt;p&gt;In the first half of Sandi&amp;#39;s presentation she presented an example of using the &lt;a href=&quot;http://en.wikipedia.org/wiki/Null_Object_pattern&quot;&gt;Null Object Pattern&lt;/a&gt; as an example of sending messages to resolve her adversion to conditionals. During this portion of the presentation, she made an interesting comment explaining how she (re)discovered this pattern herself and then presented it to her co-worker. Sandi&amp;#39;s co-worker described as &amp;quot;being a little more well read&amp;quot;, told Sandi that this pattern had a name, the &amp;quot;Null Object Pattern&amp;quot;. &lt;em&gt;(OK, so I&#39;ve cheated a little here. Sandi discusses this in her &lt;a href=&quot;https://www.youtube.com/watch?feature=player_detailpage&amp;v=9lv2lBq6x4A#t=1057&quot;&gt;Bath Ruby version&lt;/a&gt; of her talk, not in the RailsConf version.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Sandi goes on to suggest that we don&amp;#39;t need to solve specific problems ourselves, as others have already solved these for us. She doesn&amp;#39;t mention this explicitly but I interpreted this as &lt;a href=&quot;http://en.wikipedia.org/wiki/Design_Patterns&quot;&gt;Design Patterns&lt;/a&gt;. It just requires a little bit of research and reading. But where to start?&lt;/p&gt;
&lt;h2 id=&quot;two-book-recommendations&quot;&gt;Two Book Recommendations&lt;/h2&gt;
&lt;p&gt;The classic &lt;a href=&quot;http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612/ref=sr_1_3?s=books&amp;amp;ie=UTF8&amp;amp;qid=1432731268&amp;amp;sr=1-3&quot;&gt;Gang of Four Design Patterns&lt;/a&gt; book maybe a little intermediating for some, I know I&amp;#39;ve never found it appealing. However, there are some good alternatives. I recommend two.&lt;/p&gt;
&lt;p&gt;The first book that really helped enter the world of design patterns was &lt;a href=&quot;http://www.amazon.com/Design-Patterns-Explained-Perspective-Object-Oriented/dp/0321247140/ref=sr_1_1?s=books&amp;amp;ie=UTF8&amp;amp;qid=1432731268&amp;amp;sr=1-1&quot;&gt;Design Patterns Explained&lt;/a&gt; by Shalloway and Trott. As the sub-title suggests, &amp;quot;A New Perspective on Object-Oriented Design&amp;quot;, explains design patterns in the context of good OO design.&lt;/p&gt;
&lt;p&gt;Likewise, &lt;a href=&quot;http://shop.oreilly.com/product/9780596007126.do&quot;&gt;Head First Design Patterns&lt;/a&gt;, also describes design patterns in the context of OO design, connecting design patterns with principles such as &lt;strong&gt;&amp;quot;Encapsulate what varies&amp;quot; and &amp;quot;Favor composition over inheritance&amp;quot;&lt;/strong&gt;. The first chapter is a great example of presenting these principles first in an example, and then identifying it as the &lt;a href=&quot;http://en.wikipedia.org/wiki/Strategy_pattern&quot;&gt;Strategy Pattern&lt;/a&gt;. It removes the notion of using a pattern for patterns sake and focuses the discussion on solving problems, using principles and proven solutions.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;http://www.headfirstlabs.com/&quot;&gt;Head First series&lt;/a&gt; of books maybe off putting to some. Personally I&amp;#39;ve never been attracted to the series, but the Design Patterns book they have published, I feel, is first class. The examples they use really stick in your head and a great lever for accessing the patterns in the future. I&amp;#39;ve also heard good things about the &lt;a href=&quot;http://shop.oreilly.com/product/9780596008673.do&quot;&gt;Object-Oriented Analysis and Design&lt;/a&gt; book as well, although I haven&amp;#39;t read it. (If I remember correctly, I think Sandi mentioned this title when I attended her course in Durham; however I not suggesting this is an endorsement of the book by her.)&lt;/p&gt;
&lt;h2 id=&quot;don-t-fear-patterns-use-appropriately&quot;&gt;Don&amp;#39;t fear patterns, use appropriately&lt;/h2&gt;
&lt;p&gt;So rather trying to solve problems that have already been solved, I recommend investigating Design Patterns and these books are a great introduction. Design Patterns in the past do have a bad rap in the Ruby community, but I think that is no longer the case as the community matures. The original adversion to design patterns maybe due to the overuse within the Java community. Please remember, &lt;strong&gt;each design pattern needs to be used appropriately, and always consider a simpler approach&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I believe these book recommendations would be a good follow-up to Sandi&amp;#39;s book Practical Object-Oriented Design in Ruby, to &lt;strong&gt;help triangulate your understanding of OO design&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Let me know how it goes!&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/2637702661837411728'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/2637702661837411728'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2015/05/learning-oo-design-through-design.html' title='Learning OO Design through Design Patterns'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-4687467750053683646</id><published>2015-05-24T11:45:00.000-04:00</published><updated>2015-05-28T08:50:12.861-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="object-design"/><title type='text'>Rebecca Wirfs-Brock on Object Design</title><content type='html'>&lt;blockquote&gt;
Building an object-oriented application means inventing appropriate machinery. We represent real-world information, processes, interactions, relationships, even errors, by inventing objects that don&#39;t exist in the real world. We give life and intelligence to inanimate things. We take difficult-to-comprehend real-world objects and split them into simpler, more manageable software ones. We invent new objects. Each has a specific role to play in the application. Our measure of success lies in how clearly we invent a software reality that satisfies our application&#39;s requirements -- and not in how closely it remembers the real world.&lt;/blockquote&gt;

&lt;p&gt;-- Rebecca Wirfs-Brock, Object Design&lt;/p&gt;

&lt;p&gt;I pulled this quote from Avdi Grimm&#39;s excellent keynote presentation, &lt;a href=&quot;https://www.youtube.com/watch?v=IgbHzFb1hGw&quot;&gt;The Soul of Software&lt;/a&gt; as a reminder this very important idea on object-oriented design: that we invent new objects that don&#39;t have a corresponding object in the real world. If we limit our domain objects to those that are represented in the real world, we miss opportunities to &lt;strong&gt;encapsulate variation in behaviour&lt;/strong&gt; within our application.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/4687467750053683646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/4687467750053683646'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2015/05/rebecca-wirfs-brock-on-object-design.html' title='Rebecca Wirfs-Brock on Object Design'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-5532185425682820665</id><published>2014-06-20T10:31:00.000-04:00</published><updated>2014-06-20T10:41:20.274-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="presentations"/><category scheme="http://www.blogger.com/atom/ns#" term="rails"/><title type='text'>Talk: Don&#39;t Commit Your Secrets</title><content type='html'>&lt;p&gt;
On Tuesday this week, I presented a talk to &lt;a href=&quot;http://www.montrealrb.com/&quot;&gt;Montreal.rb&lt;/a&gt; on keeping your application secrets safe. Posted below is the video, slides and some follow-up questions during and after the presentation. Enjoy!&lt;/p&gt;

&lt;h2&gt;Video&lt;/h2&gt;

&lt;iframe src=&quot;//player.vimeo.com/video/98544062&quot; width=&quot;550&quot; height=&quot;309&quot; frameborder=&quot;0&quot; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;/iframe&gt;

&lt;br/&gt;
&lt;h2&gt;Slides&lt;/h2&gt;

&lt;script async class=&quot;speakerdeck-embed&quot; data-id=&quot;df6b1ad0d8cb01317e0a66c362724819&quot; data-ratio=&quot;1.33333333333333&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;

&lt;br/&gt;
&lt;h2&gt;Questions&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How can I remove a secret from your Git repository?&lt;/strong&gt;&lt;br/&gt;

GitHub has an excellent post on how to do this: &lt;a href=&quot;https://help.github.com/articles/remove-sensitive-data&quot;&gt;Remove sensitive data&lt;/a&gt;. However, if you have committed a secret to your repository which has been push to a remote, then consider that secret compromised. You will need to reset the secret (i.e. create a new API key) and configure your application using the techniques described above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How can I keep my secrets safe with an application pre-Rails 4.1?&lt;/strong&gt;&lt;br/&gt;
Check out these options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://tech.pollev.com/books/html5-apps/2-environments-with-foreman/&quot;&gt;foreman&lt;/a&gt;: recommended - any Rack app&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/bkeepers/dotenv&quot;&gt;dotenv&lt;/a&gt;: great for plain old Ruby Gems too&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/laserlemon/figaro&quot;&gt;figaro&lt;/a&gt;: YAML&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.talkingquickly.co.uk/2014/01/deploying-rails-apps-to-a-vps-with-capistrano-v3/&quot;&gt;capistrano&lt;/a&gt;: linking to a configuration file in production&lt;/li&gt;
&lt;/ul&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/5532185425682820665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/5532185425682820665'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2014/06/dont-commit-your-secrets.html' title='Talk: Don&#39;t Commit Your Secrets'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-4325259294631589997</id><published>2014-04-22T12:14:00.000-04:00</published><updated>2019-01-12T11:17:10.946-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="presentations"/><category scheme="http://www.blogger.com/atom/ns#" term="railsconf"/><title type='text'>Modeling on the Right Side of the Brain</title><content type='html'>&lt;p&gt;Update: A transcript exists on &lt;a href=&quot;https://github.com/confreaks/translations/blob/master/2014-railsconf/3321-railsconf2014-modeling-on-the-right-side-of-the-brain-transcript&quot;&gt;Confreak&#39;s GitHub translations repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Update: The presentation is now online. Unfortunately the color has been washed out when the slides were filmed, so I highly recommend you follow along with the slide deck below. Enjoy!&lt;p&gt;&lt;br /&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;//www.youtube.com/embed/ABIvpz50cKU&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;If you attended my talk at RailsConf, &lt;a href=&quot;http://www.railsconf.com/program#prop_251&quot;&gt;Modeling on the Right Side of the Brain&lt;/a&gt;, thank you so much for your support and I hope you found the talk helpful. Embedded below are the slides for my talk and resources listed below that you will find helpful in learning more about Object Modeling.&lt;/p&gt;&lt;p&gt;If you have no idea what I&#39;m talking about, here is the abstract from my talk that I gave at RailsConf 2014 in Chicago.&lt;/p&gt;&lt;p&gt;&quot;Since your first web application, you have struggled with identifying domain objects. Assigning business rules and services appears to be a talent that only other developers are born with. Fear not! Object Modeling is a learnable, teachable skill. This talk demonstrates the five essential skills you need for modeling objects and their responsibilities. Think beyond ActiveRecord and your database, and learn how color and patterns will help you explain, maintain and extend your application.&quot;&lt;/p&gt;&lt;script async class=&quot;speakerdeck-embed&quot; data-id=&quot;ad24ccf0ac400131cefb5289c90bbab3&quot; data-ratio=&quot;1.77777777777778&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;
&lt;p&gt;While the book I referenced in the talk &lt;a href=&quot;http://www.amazon.com/Java-Modeling-Color-UML-Enterprise/dp/013011510X/ref=la_B000APIAUC_1_4?s=books&amp;amp;ie=UTF8&amp;amp;qid=1398007551&amp;amp;sr=1-4&quot;&gt;Java Modeling in Color with UML&lt;/a&gt; is no longer in print, it can be sourced from Amazon if you wish to purchase a used copy. However, there is an excellent on-line resource I highly recommend authored by Stephen R. Palmer titled &lt;a href=&quot;http://www.step-10.com/SoftwareDesign/ModellingInColour/&quot;&gt;Peter Coad&#39;s &#39;Modeling in Color&#39;&lt;/a&gt; which will provide all you need to get started immediately.&lt;/p&gt;&lt;h2&gt;Books&lt;/h2&gt;&lt;p&gt;Listed below are the three key books that got me excited (and continue to do so) about Object Modeling:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/Java-Modeling-Color-UML-Enterprise/dp/013011510X/ref=la_B000APIAUC_1_4?s=books&amp;amp;ie=UTF8&amp;amp;qid=1398007551&amp;amp;sr=1-4&quot;&gt;Java Modeling in Color with UML&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/Object-Models-Strategies-Patterns-Applications/dp/0138401179/ref=sr_1_1?ie=UTF8&amp;amp;qid=1398007532&amp;amp;sr=8-1&amp;amp;keywords=object+models&quot;&gt;Object Models: Strategies, Patterns, and Applications&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/Streamlined-Object-Modeling-Patterns-Implementation/dp/0130668397/ref=sr_1_1?s=books&amp;amp;ie=UTF8&amp;amp;qid=1398007571&amp;amp;sr=1-1&amp;amp;keywords=streamlined+object+modeling&quot;&gt;Streamlined Object Modeling: Patterns, Rules, and Implementation&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;Online Resources&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;http://www.step-10.com/SoftwareDesign/ModellingInColour/&quot;&gt;Peter Coad&#39;s &#39;Modeling in Color&#39;&lt;/a&gt; authored by Stephen R. Palmer. As mentioned above, this is a great online resource to get you started today.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://mikeabney.com/som/index.html&quot;&gt;Streamlined Object Modeling&lt;/a&gt; is the book site hosted by one of the authors Mike Abney. While this is not a stand alone resource, as it does require the book to introduced some of the concepts discussed, it does provide you some insight on this specific approach buidling on Peter Coad&#39;s techniques.&lt;/p&gt;
&lt;p&gt;If there is anything else you need, please feel free to &lt;a href=&quot;http://www.firsthand.ca/contact&quot;&gt;contact me directly&lt;/a&gt; or leave a comment below.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/4325259294631589997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/4325259294631589997'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2014/04/modeling-on-right-side-of-brain.html' title='Modeling on the Right Side of the Brain'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-3339725073610755937</id><published>2013-10-23T14:31:00.001-04:00</published><updated>2013-12-10T21:20:15.065-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ebooks"/><title type='text'>Installation instructions for Quarto on OSX</title><content type='html'>&lt;p&gt;I was trying out Avdi Grimm&#39;s &lt;a href=&quot;https://github.com/avdi/quarto&quot;&gt;Quarto&lt;/a&gt; a week or so back for ebook generation. The toolchain looks very promising, but has a few dependencies that need to be installed before you can start publishing. These are listed in the &lt;a href=&quot;https://github.com/avdi/quarto#requirements&quot;&gt;README.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Here&#39;s a quick guide in getting those installed on OSX (Mountain Lion). Note I already had the following setup:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;HomeBrew&lt;/li&gt;
&lt;li&gt;pygentize&lt;/li&gt;
&lt;li&gt;xmllinit&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Command line instructions:&lt;/p&gt;&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/nicholasjhenry/7904165.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;The big one here is to ensure ~/.cabal/bin is in your path when you run the rake task to publish.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/3339725073610755937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/3339725073610755937'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2013/10/installation-instructions-for-quarto-osx.html' title='Installation instructions for Quarto on OSX'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-2104602201434140625</id><published>2013-10-08T14:32:00.001-04:00</published><updated>2013-10-08T14:54:45.645-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="heroku"/><title type='text'>Vendoring Binaires on Heroku: An Example with Aspell</title><content type='html'>&lt;p&gt;Recently I needed to install the &lt;a href=&quot;http://aspell.net/&quot;&gt;Aspell&lt;/a&gt; library on &lt;a href=&quot;https://dashboard.heroku.com/apps&quot;&gt;Heroku&lt;/a&gt; for a side project. By default a Heroku Dyno doesn&#39;t include any non-essential libraries so your left to install these on your own. This introduced me to the world of buildpacks and an awesome build tool that Heroku provides to get the job done.&lt;br/&gt;&lt;/p&gt;&lt;h2&gt;Objective&lt;/h2&gt;&lt;p&gt;The objective is to have a Rails application running with &lt;a href=&quot;https://github.com/YorickPeterse/ffi-aspell&quot;&gt;FFI::Aspell&lt;/a&gt;, a FFI binding for the Aspell library on Heroku.&lt;/p&gt;&lt;h2&gt;Heroku Buildpacks and Vendoring Binaries&lt;/h2&gt;&lt;p&gt;First, we need to configure Heroku to vendor binaries. The easiest way to do this is use the &lt;a href=&quot;https://github.com/peterkeen/heroku-buildpack-vendorbinaries&quot;&gt;Vendor Binaries buildpack&lt;/a&gt; which allows you to extract a tarball stored on S3 into your &lt;tt&gt;/app&lt;/tt&gt; directory when the application build process is triggered. This is all configured in a &lt;tt&gt;.vendor_urls&lt;/tt&gt; located in the root of your application.&lt;/p&gt;&lt;p&gt;As Heroku only supports a single buildpack by default, we need to configure it to support &lt;a href=&quot;https://github.com/ddollar/heroku-buildpack-multi&quot;&gt;multiple buildpacks&lt;/a&gt;. In our case, we need the &lt;strong&gt;Ruby buildpack&lt;/strong&gt; in addition to the &lt;strong&gt;Vendor Binaries buildpack&lt;/strong&gt;. Fortunately this is relatively easy to do when we create our new application (and can be done after the fact as well):&lt;/p&gt;&lt;pre class=&quot;brush: bash&quot;&gt;
heroku create --stack cedar --buildpack https://github.com/dollar/heroku-buildpack-multi.git
&lt;/pre&gt;&lt;p&gt;Now we have our multi buildpack application, we can configure those buildpacks in &lt;tt&gt;.buildpacks&lt;/tt&gt;:&lt;/p&gt;&lt;pre class=&quot;brush: bash&quot;&gt;
https://github.com/peterkeen/heroku-buildpack-vendorbinaries.git
https://github.com/heroku/heroku-buildpack-ruby.git
&lt;/pre&gt;&lt;p&gt;For our vendored binaries, although we haven&#39;t built it yet, we can configure it&#39;s location on S3 in &lt;tt&gt;.vendor_urls&lt;/tt&gt;:&lt;/p&gt;&lt;pre class=&quot;brush: bash&quot;&gt;
http://your-bucket.s3.amazonaws.com/aspell-0.60.6.1.tar.gz
&lt;/pre&gt;&lt;p&gt;Commit both the &lt;tt&gt;.buildpacks&lt;/tt&gt; and the &lt;tt&gt;.vendor_urls&lt;/tt&gt; files to your Rails application.&lt;/p&gt;&lt;h2&gt;Build the binary&lt;/h2&gt;&lt;p&gt;Next we need to build the binary. First, let&#39;s download and extract the source into a temporary working directory (not in your Rails application).&lt;/p&gt;&lt;pre class=&quot;brush: bash&quot;&gt;
mkdir ~/Code/temp &amp;&amp; cd ~/Code/temp
curl -o aspell-0.60.6.1.tar.gz ftp://ftp.gnu.org/gnu/aspell/aspell-0.60.6.1.tar.gz
tar -xvzf aspell-0.60.6.1.tar.gz
&lt;/pre&gt;&lt;p&gt;Now, let&#39;s create a build server on Heroku. The &lt;a href=&quot;https://github.com/heroku/vulcan&quot;&gt;Vulcan&lt;/a&gt; gem automates the process of creating the server and building the library.&lt;/p&gt;&lt;pre class=&quot;brush: bash&quot;&gt;
gem install vulcan
vulcan create vulcan-yourname
&lt;/pre&gt;&lt;p&gt;Now we&#39;re ready to build the binary:&lt;/p&gt;&lt;pre class=&quot;brush: bash&quot;&gt;
vulcan build -s ~/Code/temp/aspell-0.60.6.1 -p /tmp/aspell -c &quot;./configure --prefix=/tmp/aspell &amp;&amp; make install&quot;
&lt;/pre&gt;&lt;p&gt;You will notice that we configure the library to be installed in &lt;tt&gt;/tmp/aspell&lt;/tt&gt; using the &lt;tt&gt;prefix&lt;/tt&gt; option. We also need to tell Vulcan using the &lt;tt&gt;-p&lt;/tt&gt; option where the compiled library will be located. At the completion of the build, a tarball is then download to your &lt;tt&gt;/tmp&lt;/tt&gt; directory.&lt;/p&gt;&lt;p&gt;You can now copy the tarball from &lt;tt&gt;/tmp/aspell-0.60.6.tgz&lt;/tt&gt; to the S3 bucket specified in &lt;tt&gt;.vendor_urls&lt;/tt&gt;. Ensure the read permission on the uploaded file can viewed by &quot;world&quot;, otherwise it won&#39;t be accessible when you deploy your application and you will receive the following errors:&lt;/p&gt;&lt;pre&gt;
-----&gt; Found a .vendor_urls file
       Vendoring http://yourbucket-heroku.s3.amazonaws.com/aspell-0.60.6.tgz

gzip: stdin: not in gzip format
tar: Child returned status 1
tar: Exiting with failure status due to previous errors

 !     Push rejected, failed to compile Multipack app
&lt;/pre&gt;&lt;h2&gt;Build the supporting dictionary files&lt;/h2&gt;&lt;p&gt;Typically we would be done at this point, but we need to compile the dictionary files that Aspell uses separately. This makes the process a little more complicated.&lt;/p&gt;&lt;p&gt;We&#39;re going to use our Vulcan build server to compile the dictionary files. This requires starting up a shell, downloading the Aspell tarbar we built previously and extracting it into the original installation directory.&lt;/p&gt;&lt;pre class=&quot;brush: bash&quot;&gt;
heroku run bash --app vulcan-yourname
cd /tmp
mkdir aspell &amp;&amp; cd aspell
curl -o aspell-0.60.6.tgz http://yourbucket-heroku.s3.amazonaws.com/aspell-0.60.6.tgz
tar -xzvf aspell-0.60.6.tgz
&lt;/pre&gt;&lt;p&gt;Now we&#39;re ready to build the dictionary files:&lt;/p&gt;&lt;pre class=&quot;brush: bash&quot;&gt;
export PATH=$PATH:/tmp/aspell/bin
curl -o aspell6-en-7.1-0.tar.bz2 ftp://ftp.gnu.org/gnu/aspell/dict/en/aspell6-en-7.1-0.tar.bz2
tar -xvf aspell6-en-7.1-0.tar.bz2
cd aspell6-en-7.1-0
./configure &amp;&amp; make install
&lt;/pre&gt;&lt;p&gt;At this point you will see output similar to this:&lt;/p&gt;&lt;pre&gt;
/tmp/aspell/bin/prezip-bin -d &lt; en-common.cwl | /tmp/aspell/bin/aspell  --lang=en create master ./en-common.rws
/tmp/aspell/bin/prezip-bin -d &lt; en-variant_0.cwl | /tmp/aspell/bin/aspell  --lang=en create master ./en-variant_0.rws
/tmp/aspell/bin/prezip-bin -d &lt; en-variant_1.cwl | /tmp/aspell/bin/aspell  --lang=en create master ./en-variant_1.rws
/tmp/aspell/bin/prezip-bin -d &lt; en-variant_2.cwl | /tmp/aspell/bin/aspell  --lang=en create master ./en-variant_2.rws
...
&lt;/pre&gt;&lt;p&gt;Once the build is completed you can test Aspell is working correctly with:&lt;/p&gt;&lt;pre class=&quot;brush: bash&quot;&gt;
echo &quot;helloz&quot; | aspell -a
&lt;/pre&gt;&lt;p&gt;We&#39;re almost there. Now just copy the dictionary files over to our original build for Aspell in &lt;tt&gt;/lib/aspell-0.60/&lt;/tt&gt; We will create a new tarball which includes the dictionary files:&lt;/tt&gt;&lt;/p&gt;&lt;pre class=&quot;brush: bash&quot;&gt;
cp *.rws *.alias *.multi *.dat ../lib/aspell-0.60/.
cd ..
tar -czvf aspell-0.60.6.tgz bin include lib share
&lt;/pre&gt;&lt;p&gt;Finally, transfer the new tarball &lt;tt&gt;aspell-0.60.6.tgz&lt;/tt&gt; to your local machine and upload to S3 again replacing our original tarball.&lt;/p&gt;&lt;h2&gt;Deployment&lt;/h2&gt;&lt;p&gt;Before deploying you will need to configure &lt;tt&gt;LD_LIBRARY_PATH&lt;/tt&gt;, the path used by the dynamic loader  to load libraries into dynamically linked executables. Otherwise, the following error is raised:&lt;/p&gt;&lt;pre&gt;
aspell: error while loading shared libraries: libaspell.so.15: cannot open shared object file: No such file or directory
&lt;/pre&gt;&lt;p&gt;This is easy to do:&lt;/p&gt;&lt;pre class=&quot;brush: bash&quot;&gt;
heroku config:add LD_LIBRARY_PATH=/app/lib
&lt;/pre&gt;&lt;p&gt;Now let&#39;s deploy our application. Remember to include the FFI::Aspell in our Gemfile and bundle. As long as you have your application setup correctly with Heroku you can then:&lt;/p&gt;&lt;pre class=&quot;brush: bash&quot;&gt;
git push heroku
&lt;/pre&gt;&lt;p&gt;On a successful build your output will begin with the following (note the vendoring of http://your-bucket.s3.amazonaws.com/aspell-0.60.6.tgz):&lt;/p&gt;&lt;pre&gt;
-----&gt; Fetching custom git buildpack... done
-----&gt; Multipack app detected
=====&gt; Downloading Buildpack: https://github.com/peterkeen/heroku-buildpack-vendorbinaries.git
=====&gt; Detected Framework: VendorBinaries
-----&gt; Found a .vendor_urls file
       Vendoring http://your-bucket.s3.amazonaws.com/aspell-0.60.6.tgz
=====&gt; Downloading Buildpack: https://github.com/heroku/heroku-buildpack-ruby.git
=====&gt; Detected Framework: Ruby/Rails
-----&gt; Using Ruby version: ruby-2.0.0
-----&gt; Installing dependencies using Bundler version 1.3.2
       Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin --deployment
       Fetching gem metadata from https://rubygems.org/..........
       Fetching gem metadata from https://rubygems.org/..
       Installing rake (10.1.0)
&lt;/pre&gt;&lt;h2&gt;Test the FFI::Aspell Gem&lt;/h2&gt;&lt;p&gt;The moment of truth! Let&#39;s run a Rails console to test the FFI:Aspell gem.&lt;/p&gt;&lt;pre class=&quot;brush: bash&quot;&gt;
heroku run console
&lt;/pre&gt;&lt;p&gt;At the Rails console:&lt;/p&gt;&lt;pre class=&quot;brush: bash&quot;&gt;
speller = FFI::Aspell::Speller.new(&#39;en_US&#39;, &#39;dict-dir&#39; =&gt; &#39;/app/lib/aspell-0.60&#39;)
speller.correct?(&#39;cookie&#39;) # =&gt; true
&lt;/pre&gt;&lt;p&gt;Note we need to specify the &lt;tt&gt;dict-dir&lt;/tt&gt; option since the Aspell library looks for it in &lt;tt&gt;/tmp/aspell/lib/aspell-0.60&lt;/tt&gt; by default (based on the &lt;tt&gt;prefix&lt;/tt&gt; option we used when we compiled it). If you were to execute the binary directly from the shell you would also need to include this option. For example:&lt;/p&gt;&lt;pre class=&quot;brush: bash&quot;&gt;
echo &quot;helloz&quot; | aspell -a --dict-dir /app/lib/aspell-0.60
&lt;/pre&gt;&lt;p&gt;If you don&#39;t include the &lt;tt&gt;dict-dir&lt;/tt&gt; option, the FFI:Aspell library will crash.&lt;/p&gt;&lt;h2&gt;Troubleshooting&lt;/h2&gt;&lt;p&gt;If you have problems, it best to try to run the Aspell library directly from the shell using the example command above.&lt;/p&gt;&lt;p&gt;If you receive the following error:&lt;/p&gt;&lt;pre&gt;
Error: No word lists can be found for the language &quot;en_US&quot;.
&lt;/pre&gt;&lt;p&gt;Then the path to the dictionary files is not correct.&lt;/p&gt;&lt;h2&gt;References&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://devcenter.heroku.com/articles/buildpack-binaries&quot;&gt;Packaging Binary Buildpack Dependencies&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;
https://github.com/heroku/vulcan&quot;&gt;Vulcan&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/peterkeen/heroku-buildpack-vendorbinaries&quot;&gt;Heroku Vendor Binaries Buildpack&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/ddollar/heroku-buildpack-multi&quot;&gt;Heroku Multi Buildpack&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/a/14829672&quot;&gt;Using Hunspell With Heroku&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
			
</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/2104602201434140625'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/2104602201434140625'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2013/10/vendoring-binaires-on-heroku-example.html' title='Vendoring Binaires on Heroku: An Example with Aspell'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-4781617146896444291</id><published>2013-10-08T14:31:00.001-04:00</published><updated>2013-10-08T14:31:53.593-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="agile"/><category scheme="http://www.blogger.com/atom/ns#" term="presentations"/><title type='text'>Talk: Meet Trello</title><content type='html'>&lt;p&gt;A couple of months ago I gave a presentation on &lt;a href=&quot;https://trello.com/&quot;&gt;Trello&lt;/a&gt; for a lunch and learn at &lt;a href=&quot;http://www.godynamo.com/&quot;&gt;Dynamo&lt;/a&gt;. Trello is a collaborative project planning tool that I was trying out at the time. This presentation shares my findings on how to use Trello for project management in an agile development context. Enjoy!&lt;/p&gt;&lt;iframe src=&quot;//player.vimeo.com/video/76427639&quot; width=&quot;500&quot; height=&quot;281&quot; frameborder=&quot;0&quot; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;/iframe&gt;&lt;p&gt;&lt;a href=&quot;http://vimeo.com/76427639&quot;&gt;Meet Trello&lt;/a&gt; from &lt;a href=&quot;http://vimeo.com/user8958367&quot;&gt;DynamoMTL&lt;/a&gt; on &lt;a href=&quot;https://vimeo.com&quot;&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/4781617146896444291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/4781617146896444291'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2013/10/meet-trello.html' title='Talk: Meet Trello'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-5911379780505950613</id><published>2013-10-07T13:55:00.001-04:00</published><updated>2013-10-07T14:03:35.834-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="launch"/><title type='text'>Recently Launched: Quarterly Co.</title><content type='html'>&lt;p&gt;My last project at &lt;a href=&quot;http://www.godynamo.com&quot;&gt;Dynamo&lt;/a&gt; involved the porting of a Rails application integrated with Recurly to Spree for &lt;a href=&quot;http://quarterly.co&quot;&gt;Quarterly Co.&lt;/a&gt;, an LA-based company. Quarterly is a subscription service, curating gifts by their selection of contributors shipped every three-months. Check out this &lt;a href=&quot;http://quarterlyco.tumblr.com/post/7849330591/why-im-starting-quarterly-co&quot;&gt;beautifully written blog post&lt;/a&gt; written by Quarterly&#39;s founder, Zach Frechette, describing why he started Quarterly.&lt;/p&gt;&lt;h2&gt;Key Objective&lt;/h2&gt;&lt;p&gt;The key objective for this project was to move from their current model of billing their subscribers every three-months, to billing when a curated gift is shipped. Moving to this model also required some solid order management that their current application didn&#39;t provide. Spree, an open source e-commerce platform, was the chosen as the foundation for Quarterly&#39;s online business.&lt;/p&gt;&lt;h2&gt;Technical Challenges&lt;/h2&gt;&lt;p&gt;There were some interesting technical challenges for this project that included:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Customizing Spree&#39;s &quot;Product and Order&quot;-based data model to support subscriptions.&lt;/li&gt;&lt;li&gt;Migrating subscription data from two data sources, Recurly and the custom Rails application.&lt;/li&gt;&lt;li&gt;Migrating an existing design to Spree&#39;s opinionated checkout flow.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Check out the screenshot&#39;s below or &lt;a href=&quot;http://quarterly.co&quot;&gt;visit the site&lt;/a&gt;, you might find a contributor that you want to subscribe to. Treat yourself!&lt;/p&gt;&lt;p&gt;(A shout out to Rodrigo Dalcin, a Front-end Developer at Dynamo, who worked porting the front-end to Spree for this project. Thank you for all your help!)&lt;/p&gt;&lt;h2&gt;Home Page&lt;/h2&gt;&lt;img src=&quot;http://firsthand-blog.s3.amazonaws.com/2013/10/quarterly-home.png&quot; alt=&quot;Home Page&quot; border=&quot;0&quot; /&gt;&lt;h2&gt;Contributor&#39;s Page&lt;/h2&gt;&lt;img src=&quot;http://firsthand-blog.s3.amazonaws.com/2013/10/quarterly-contributor.png&quot; alt=&quot;Contributor&#39;s Page&quot; border=&quot;0&quot; /&gt;
			</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/5911379780505950613'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/5911379780505950613'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2013/10/recently-launched-quarterly-co.html' title='Recently Launched: Quarterly Co.'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-1420341967533412880</id><published>2013-10-07T11:24:00.001-04:00</published><updated>2013-12-14T16:55:08.546-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="rails"/><title type='text'>Rails: undefined method `action&amp;#39; for YourController:Class</title><content type='html'>&lt;p&gt;You will receive this error if you have created your controller class manually (i.e. without the Rails generators) and have not inherited from &lt;tt&gt;ApplicationController&lt;/tt&gt;. For example&lt;/p&gt;&lt;script src=&quot;https://gist.github.com/nicholasjhenry/7965410.js?file=home-controller-01.rb&quot;&gt;&lt;/script&gt;&lt;br /&gt;
&lt;p&gt;This is easily fixed by adding &lt;tt&gt;ApplicationController&lt;/tt&gt; as the parent. Note the change on line #1.&lt;/p&gt;&lt;script src=&quot;https://gist.github.com/nicholasjhenry/7965410.js?file=home-controller-02.rb&quot;&gt;&lt;/script&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/1420341967533412880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/1420341967533412880'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2013/10/rails-undefined-method-action-for.html' title='Rails: undefined method `action&amp;#39; for YourController:Class'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-80117701297207131</id><published>2013-07-20T19:18:00.001-04:00</published><updated>2013-07-20T19:20:56.983-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="mysql"/><category scheme="http://www.blogger.com/atom/ns#" term="ruby"/><title type='text'>mysql2 installation issues on OSX 10.8.4 (homebrew install)</title><content type='html'>&lt;p&gt;Installing mysql2 Ruby gem on 10.8.4 with a home-brew install may raise the following error:&lt;/p&gt;&lt;code&gt;mysql.h is missing.  please check your installation of mysql and try again.&lt;/code&gt;&lt;p&gt;Removing the following options from cflags in mysql_config &lt;code&gt;vim `which mysql_config`&lt;/code&gt; resolved the issue:&lt;/p&gt;&lt;code&gt; -Wno-null-conversion -Wno-unused-private-field&lt;/code&gt;&lt;p&gt;Credit: &lt;a href=&quot;https://github.com/brianmario/mysql2/issues/383&quot;&gt;&lt;/a&gt;https://github.com/brianmario/mysql2/issues/383&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/80117701297207131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/80117701297207131'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2013/07/mysql2-installation-issues-on-osx-1084.html' title='mysql2 installation issues on OSX 10.8.4 (homebrew install)'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-4188886343044365635</id><published>2013-06-07T12:06:00.000-04:00</published><updated>2014-07-11T12:07:59.830-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="developer-challenge"/><title type='text'>June Developer Challenge: Share the Knowledge</title><content type='html'>&lt;p&gt;Note: This was originally posted to the &lt;a href=&quot;http://blog.godyanmo.com&quot;&gt;Dynamo Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Last month we leveled-up with &lt;a href=&quot;/2013/05/may-developer-challenge-crush-your.html&quot;&gt;Crush Your Achilles&amp;#8217; Heel&lt;/a&gt;. This month, it&amp;#8217;s about helping your team members level-up with &amp;#8220;Share the Knowledge&amp;#8221;. This month&amp;#8217;s focus is about sharing knowledge with your team mates. After years as a solo freelancer, one of the great joys I now experience working with a team, is the learning gained from my team members. I also love sharing what I&amp;#8217;ve learned. However, we need to be proactive about sharing to allow others to benefit.&lt;/p&gt;

&lt;p&gt;This month, your challenge is to take what you learned from last month&amp;#8217;s challenge, and share it with your team members. At Dynamo, we have a number of avenues for sharing information with others. These include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vimeo.com/user8958367&quot;&gt;Workshop Wednesdays&lt;/a&gt;: Lunch-time sessions for presentations and discussions&lt;/li&gt;
&lt;li&gt;Dynamo Central: A wiki hosted on &lt;a href=&quot;https://github.com&quot;&gt;GitHub&lt;/a&gt; to share process and procedures&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.godynamo.com/&quot;&gt;Dynamo Blog&lt;/a&gt;: This blog to share with the greater design and development community&lt;/li&gt;
&lt;li&gt;Dynamo Retreat: A yearly event to review what&amp;#8217;s working, and what&amp;#8217;s not&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;So choose something valuable from last month&amp;#8217;s challenge to share. If you didn&amp;#8217;t complete the challenge, I&amp;#8217;m sure you have something else. Do you have a checklist or procedure documented in your notebook? Do you have a process that you&amp;#8217;re benefiting from, but no one knows about it? I encourage you to share this knowledge as a presentation, a blog post, or simply as a checklist on the wiki.&lt;/p&gt;

&lt;p&gt;Your Developer Challenge for the month of June has been issued! Please let us know what you attend to share this month in the comments below.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/4188886343044365635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/4188886343044365635'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2013/06/june-developer-challenge-share-knowledge.html' title='June Developer Challenge: Share the Knowledge'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-1550558856789239607</id><published>2013-05-07T07:33:00.001-04:00</published><updated>2013-05-07T07:33:33.385-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="agile"/><title type='text'>Ron Jeffries on Requirements</title><content type='html'>&lt;p&gt;This is one of my favourite quotes on requirements:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Most of us were taught to write down all our requirements at the very beginning of the project. There are only three things wrong with this: “requirements,” “the very beginning,” and “all.” At the very beginning, we know less about our project than we’ll ever know again. This is the worst possible moment to be making firm decisions about what we “require.”&lt;/p&gt;&lt;p&gt;From &lt;a href=&quot;http://pragprog.com/magazines/2013-02/estimation-is-evil&quot;&gt;Estimation is Evil&lt;/a&gt;, Ron Jeffries: Signatory of the Manifesto for Agile Software Development ￼&lt;/p&gt;&lt;/blockquote&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/1550558856789239607'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/1550558856789239607'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2013/05/ron-jeffries-on-requirements.html' title='Ron Jeffries on Requirements'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-473263621463317566</id><published>2013-05-06T12:03:00.000-04:00</published><updated>2014-07-11T12:04:22.657-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="developer-challenge"/><title type='text'>May Developer Challenge: Crush Your Achilles&#39; Heel</title><content type='html'>&lt;p&gt;Note: This was originally posted to the &lt;a href=&quot;http://blog.godyanmo.com&quot;&gt;Dynamo Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We all have it. &lt;strong&gt;It&amp;#8217;s that gap in our knowledge that slows our development down.&lt;/strong&gt; It&amp;#8217;s your Achilles&amp;#8217; Heel. Every day we use the same tool, but we&amp;#8217;re never really take the time to understand the fundamentals of how it works. This might be Git, SQL, or Regular Expressions. It might be a concept that we struggle with, but have never said, &amp;#8220;OK, I need to dedicate some time to really understand this&amp;#8221;. So this month, it&amp;#8217;s time to crush it.&lt;/p&gt;

&lt;p&gt;Inspired by RailsConf talk &amp;#8221;&lt;a href=&quot;http://www.railsconf.com/2013/talks#talk-3&quot;&gt;Nobody will Train You but You&lt;/a&gt;&amp;#8221; from Zach Briggs, your challenge for the month of May is to identify a weakness in  your development knowledge, and proactively train yourself in that area. Since the beginning of the year, I have been proactively addressing weakness in my development knowledge. Here are examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;SQL&lt;/em&gt;: After years of working with Rail&amp;#8217;s ORM, ActiveRecord, I felt my knowledge of SQL beginning to wane. I went back to basics and completed &lt;a href=&quot;https://class2go.stanford.edu/db/Winter2013/preview/&quot;&gt;Standford University&amp;#8217;s&lt;/a&gt; course on databases. After this course,  I had cleared out those SQL cobwebs, and back to feeling comfortable working at the SQL console again.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;NewRelic&lt;/em&gt;: Normally I use &lt;a href=&quot;http://newrelic.com/&quot;&gt;NewRelic&lt;/a&gt; in periods of stress, trying to resolve a performance issue. This means revisiting and learning the UI while I&amp;#8217;m trying to solve a problem. By dedicating two afternoons to &lt;a href=&quot;https://newrelic.com/docs&quot;&gt;reading the documentation&lt;/a&gt; and reviewing a live application&amp;#8217;s metrics, I feel much more prepared to dive in when there&amp;#8217;s a performance fire.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Performance Optimization&lt;/em&gt;: I&amp;#8217;ve addressed performance in an ad-hoc manner in the past. To resolve this. I have dedicated time to review various resources on performance including the &lt;a href=&quot;https://www.youtube.com/playlist?list=PLuVcDOUVjW2ePvFapFSHBZ71ya2fLHZS5&quot;&gt;Scaling Rails&lt;/a&gt; series (which is developed a couple a few years ago, but still relevant). This resulted in a cheat sheet that I actively use to think about performance from day one.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;But this challenge doesn&amp;#8217;t end with passively reading a book or watching a screencast. &lt;strong&gt;It&amp;#8217;s about reinforcing your knowledge by sharing with others.&lt;/strong&gt; You really understand a topic, when you share it with others. So after spending the month learning, next month I encourage you to write a blog post, perform a workshop or write a &lt;a href=&quot;https://github.com/nicholasjhenry/mongodb_basics/blob/master/spec/queries_spec.rb&quot;&gt;test suite&lt;/a&gt; demonstrating what you have learnt.&lt;/p&gt;

&lt;p&gt;So here&amp;#8217;s the plan:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Take the week to &lt;strong&gt;identify your areas of weakness&lt;/strong&gt;. As you go through your day, write down these areas as you experience them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pick an area&lt;/strong&gt; at the end of the week to work on. At this point, you might want to consider how you will share your knowledge. Please share your topic in the comments below.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Develop a plan&lt;/strong&gt; on how you&amp;#8217;re going to improve your knowledge. Don&amp;#8217;t try to be too ambitious, keep your goals realistic. Think &lt;a href=&quot;http://en.wikipedia.org/wiki/SMART_criteria&quot;&gt;SMART&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Work through your plan&lt;/strong&gt; for the month.&lt;/li&gt;
&lt;li&gt;At the end of this month commit to how you would like to &lt;strong&gt;share your knowledge&lt;/strong&gt;. We will prepare to share our knowledge in the month of June.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;OK, your Developer Challenge of the month of May has been issued! Please don&amp;#8217;t forget to share your topic in the comments below. &lt;strong&gt;Good luck with crushing your Achilles&amp;#8217; Heel&lt;/strong&gt;.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/473263621463317566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/473263621463317566'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2013/05/may-developer-challenge-crush-your.html' title='May Developer Challenge: Crush Your Achilles&#39; Heel'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-8166673285273699482</id><published>2013-04-27T11:58:00.000-04:00</published><updated>2014-07-11T12:01:34.308-04:00</updated><title type='text'>Task Lists in Our Pull Requests</title><content type='html'>&lt;p&gt;Note: This was originally posted to the &lt;a href=&quot;http://blog.godyanmo.com&quot;&gt;Dynamo Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since we have been using &lt;a href=&quot;/blog/2013/04/05/april-developer-challenge-feature-development-with-pull-requests/&quot;&gt;Pull Requests to drive development&lt;/a&gt; over a month or so now, &lt;a href=&quot;https://github.com/blog/1375-task-lists-in-gfm-issues-pulls-comments&quot;&gt;GitHub Task Lists&lt;/a&gt; have been an important component. Personally, I have been using them to document my initial thoughts/brainstorming on tasks  required to complete a feature and the whole team have been using them pervasively. They also have an impact on issues (from the GitHub post):&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;You can use task lists to break down large issues and discourage the creation of many microscopic issues, allowing you to focus on interacting with the list instead of editing Markdown.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;A Task List can be created in PR comments using &lt;a href=&quot;https://help.github.com/articles/github-flavored-markdown&quot;&gt;GitHub Flavored Markdown&lt;/a&gt;. Here&amp;#8217;s an example of a Task List from a project I&amp;#8217;m currently working on:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://dynamo-blog.s3.amazonaws.com/2013/04/27-task-list.png&quot; alt=&quot;Task List Example&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And they are easily created with a bit of Markdown:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://dynamo-blog.s3.amazonaws.com/2013/04/27-task-list-markdown.png&quot; alt=&quot;Markdown Example&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Oh, and a power tip: pressing &amp;#8216;M&amp;#8217; on the keyboard will display a Markdown cheat sheet.&lt;/p&gt;

&lt;p&gt;How are you using GitHub Tasks Lists? Let us know in the comments.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/8166673285273699482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/8166673285273699482'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2013/04/task-lists-in-our-pull-requests.html' title='Task Lists in Our Pull Requests'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-5339424067280853006</id><published>2013-04-26T09:04:00.001-04:00</published><updated>2013-04-26T09:10:46.971-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="launch"/><title type='text'>Recently Launched: Tarkett Sports CMS and Websites</title><content type='html'>&lt;p&gt;An ongoing project I have been working on at &lt;a href=&quot;http://www.godynamo.com&quot; title=&quot;http://www.godynamo.com&quot;&gt;Dynamo&lt;/a&gt; over the last year with &lt;a href=&quot;http://www.cekoya.com/&quot; title=&quot;http://www.cekoya.com/&quot;&gt;Hugo Frappier&lt;/a&gt; is a custom CMS for Tarkett Sports, a division of the Tarkett Group, &quot;a worldwide leader of innovative and sustainable flooring and sports surface solutions&quot;.&lt;/p&gt;&lt;h2&gt;A multi-Site, multi-lingual CMS&lt;/h2&gt;&lt;p&gt;Tarkett Sports required a multi-site, multi-lingual CMS to serve all the sites of their subdivisions. FieldTurf (North America) was the first to be launched on the new platform, followed by FieldTurf Europe and an API for their iPad sales tool, &quot;Link&quot;. At the time of writing, Beynon Sports Surfaces and Tarkett Sports Indoor (North America) are set to launch within the month.&lt;/p&gt;&lt;h2&gt;Built on Ruby on Rails and MongoDB&lt;/h2&gt;&lt;p&gt;The CMS was built with the usual Rails stack, however &lt;a href=&quot;http://www.mongodb.org/&quot; title=&quot;http://www.mongodb.org/&quot;&gt;MongoDB&lt;/a&gt; was used with &lt;a href=&quot;http://mongoid.org/&quot; title=&quot;http://mongoid.org/&quot;&gt;Mongoid&lt;/a&gt;, an Object-Document-Mapper, instead of ActiveRecord and a relational database. This was my first venture in the world of NoSQL, and working with a schema less data store was a perfect match for the CMS. However, it did require a new way of thinking, such as being comfortable with de-normalizing data structures and ensuring those data structures can be properly index. For example, MongoDB does not allow indexing of parallel arrays.&lt;/p&gt;&lt;h2&gt;Support a large content-base&lt;/h2&gt;&lt;p&gt;Why a custom CMS? Why didn&#39;t we just use one of the prominent offerings such as RefineryCMS? I&#39;ve implemented five RefineryCMS installations over the last couple of years, and Refinery&#39;s sweet spot is small websites. Tarkett Sports currently holds over 10,000 content items. Refinery&#39;s UI and tree data structure is just not appropriate for such a large content-base.&lt;/p&gt;&lt;h2&gt;Publish content collections anywhere in the page hierarchy&lt;/h2&gt;&lt;p&gt;We also took a novel approach to the page hierarchy. With platforms such as RefineryCMS and Radiant, structured content (think news and product catalog) containing large data sets are typically supported by creating custom Rails model view, and controller classes. There&#39;s usually wrangling to unify the site URLs with the routing system. The Tarkett Sports CMS supports the concept of a collection. A collection of structured content, small or large, can be published anywhere within the page hierarchy. No URL wrangling required, no custom controller class. Collections are a first class citizen.&lt;/p&gt;&lt;h2&gt;Reduce custom classes, increase content type re-use&lt;/h2&gt;&lt;p&gt;The benefit of all this is that it has reduced the number of custom classes required for a site by increasing the reuse of existing collections and content types. In the past, I have found myself creating custom controllers and models just to support a different content type with the same structure just so I can use it in a different part of the page hierarchy. The concept of publishable collections has solved this.&lt;/p&gt;&lt;p&gt;Below are a few screen shots, showcasing the different sites and portions of the administration screens.&lt;/p&gt;&lt;h2&gt;FieldTurf (North America) Home Page&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;http://firsthand-blog.s3.amazonaws.com/2013/04/tarkett-home-field-turf.png&quot; alt=&quot;FieldTurf (North America) Home Page&quot; border=&quot;0&quot; /&gt;&lt;/p&gt;&lt;h2&gt;FieldTurf (Europe) Home Page&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;http://firsthand-blog.s3.amazonaws.com/2013/04/tarkett-home-europe.png&quot; alt=&quot;FieldTurf (Europe) Home Page&quot; border=&quot;0&quot; /&gt;&lt;/p&gt;&lt;h2&gt;FieldTurf Products&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;http://firsthand-blog.s3.amazonaws.com/2013/04/tarkett-products.png&quot; alt=&quot;FieldTurf Products&quot; width=&quot;&quot; height=&quot;&quot; border=&quot;0&quot; /&gt;&lt;/p&gt;&lt;h2&gt;FieldTurf Product Detail&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;http://firsthand-blog.s3.amazonaws.com/2013/04/tarkett-product.png&quot; alt=&quot;FieldTurf Product Detail&quot; width=&quot;&quot; height=&quot;&quot; border=&quot;0&quot; /&gt;&lt;/p&gt;&lt;h2&gt;Tarkett Sports CMS Admin: Pages&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;http://firsthand-blog.s3.amazonaws.com/2013/04/tarkett-admin-pages.png&quot; alt=&quot;Admin Pages&quot; border=&quot;0&quot; /&gt;&lt;/p&gt;&lt;h2&gt;Tarkett Sports CMS Admin: Page Detail&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;http://firsthand-blog.s3.amazonaws.com/2013/04/tarkett-admin-page-detail.png&quot; alt=&quot;Admin Page Detail&quot; border=&quot;0&quot; /&gt;&lt;/p&gt;&lt;h2&gt;Tarkett CMS Sports Admin: Page Publishing&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;http://firsthand-blog.s3.amazonaws.com/2013/04/tarkett-admin-publish.png&quot; alt=&quot;Admin Page Publishing&quot; border=&quot;0&quot; /&gt;&lt;/p&gt;







</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/5339424067280853006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/5339424067280853006'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2013/04/recently-launched-tarkett-sports-cms.html' title='Recently Launched: Tarkett Sports CMS and Websites'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-8830688385833699169</id><published>2013-04-22T07:21:00.001-04:00</published><updated>2013-04-22T07:21:31.776-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="vim"/><title type='text'>Open Gems with vim-bundler</title><content type='html'>&lt;p&gt;When working with platforms such as Spree and RefineryCMS it&#39;s more than likely that I will be extending their models more often that not. This means opening the Gem to identify a specific behaviour I want to override. Vim is my text editor of choice, and I typically try to restrict my self to one instance of the editor running. It makes working with multiple buffers a lot easier! Whenever I want to open a Ruby Gem, it always irks me that I have to open another instance of the editor, in a separate window/pane (although Tmux reduces the pain of this a wee bit).&lt;/p&gt;&lt;p&gt;Vim does offer a &lt;a href=&quot;http://ajayfromiiit.wordpress.com/2009/10/21/server-and-client-mode-in-vim/&quot;&gt;client-server&lt;/a&gt; option, but admittedly I couldn&#39;t get this working and in my search I came across &lt;a href=&quot;https://github.com/tpope/vim-bundler&quot;&gt;Tim Pope&#39;s vim-bundler&lt;/a&gt;. From the README:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;An internalized version of &lt;tt&gt;bundle open&lt;/tt&gt; : &lt;tt&gt;:Bopen&lt;/tt&gt; (and &lt;tt&gt;:Bsplit&lt;/tt&gt; , &lt;tt&gt;:Btabedit&lt;/tt&gt; , etc.).&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Exactly what I wanted, a way to `bundle open` within Vim. Here&#39;s a quick demo of using vim-bundler to open Spree&#39;s `Order` model and navigate to the `add_variant` method.&lt;/p&gt;&lt;p&gt;&lt;iframe src=&quot;http://player.vimeo.com/video/64499319&quot; width=&quot;500&quot; height=&quot;306&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://vimeo.com/64499319&quot;&gt;vim-bundler&lt;/a&gt; from &lt;a href=&quot;http://vimeo.com/firsthand&quot;&gt;Nicholas Henry&lt;/a&gt; on &lt;a href=&quot;http://vimeo.com&quot;&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/8830688385833699169'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/8830688385833699169'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2013/04/open-gems-with-vim-bundler.html' title='Open Gems with vim-bundler'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-6038653580299884355</id><published>2013-04-16T11:57:00.000-04:00</published><updated>2014-07-11T11:57:42.827-04:00</updated><title type='text'>Creating Dedicated, Focused Time</title><content type='html'>&lt;p&gt;Note: This was originally posted to the &lt;a href=&quot;http://blog.godyanmo.com&quot;&gt;Dynamo Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Working on multiple projects in a single day has a mental cost and less efficient than dedicating time to a single project. Segmenting the week to work on a specific project and allocating time for the unexpected is one possible solution for reducing the cost of context switching.&lt;/p&gt;

&lt;p&gt;Yesterday we had a terrific conversation in our weekly project mini-retrospective about the cost of context switching in the studio. This is a problem that any service-based company with multiple clients has, but it’s a tough problem specifically when providing creative services. &lt;strong&gt;At Dynamo, we’re working on engaging problems, which require dedicated, focused time to solve&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;However, during the day we might be working on multiple projects, and there are maintenance tasks competing for our attention. &lt;strong&gt;So how might we reduce the context switching to create dedicated, focused time?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our solution has four components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Segment the week to dedicate &lt;strong&gt;specific days to a project&lt;/strong&gt;, depending on the velocity required.&lt;/li&gt;
&lt;li&gt;Assign a &lt;strong&gt;dedicated day to work on maintenance&lt;/strong&gt;. This is planning for the unexpected, and the unexpected always happens.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Publish your schedule&lt;/strong&gt;. Let your team members and project managers know what days you have assigned.&lt;/li&gt;
&lt;li&gt;Project managers will be &lt;strong&gt;mindful of these assigned days&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;The last component is the key. When project managers know the maintenance day of the project’s maintainer, then expectations can be appropriately set with the client when a maintenance task can be completed.&lt;/p&gt;

&lt;p&gt;Of course, emergencies and rush tasks are always going to arise. But, in reality these are rare. So I plan to put this into practice, and I will let you know how it goes. How do you reduce the context switching to create dedicated, focused time? Let us know in the comments.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/6038653580299884355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/6038653580299884355'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2013/04/creating-dedicated-focused-time.html' title='Creating Dedicated, Focused Time'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-5096608649281527367</id><published>2013-04-09T08:07:00.001-04:00</published><updated>2013-04-09T18:48:11.254-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="life hacks"/><category scheme="http://www.blogger.com/atom/ns#" term="productivity"/><title type='text'>Taming the pile of unread books</title><content type='html'>&lt;p&gt;Recently I posted to Facebook:&lt;/p&gt;&lt;blockquote&gt;You know you have a book buying problem when... you discover that you have two copies of the same book on your bookshelf. Unread.&lt;/blockquote&gt;&lt;p&gt;&lt;strong&gt;Yes, I have a book buying problem.&lt;/strong&gt; And after that post I decided it was time to do something about it. I love reading. I find it extremely motivating and inspiring. But having a few dozen unread or partially started books is not only a waste of money, but just another open loop in my life that just doesn&#39;t need to be there. Jumping from book to book also inhibits in my ability to really understanding a book.&lt;/p&gt;&lt;p&gt;And before you start thinking I&#39;m talking about a pile of trashy romance novels, I am talking about computer and business related books!&lt;/p&gt;&lt;p&gt;&lt;strong&gt;So how did it get this way?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;I have always had a stack of unread books around, but I typically got through the queue. However, with eBooks it really has got out of control. I start with reading an inspiring blog post, or watching a video of a conference talk, it references a book and wham! Next moment, I&#39;m online purchasing that sucker.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;So what have I done to resolve this?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;It was pretty simple really. I present to you, my three step plan:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;First, &lt;strong&gt;I took inventory&lt;/strong&gt;. I identified the books as unopened, &quot;briefly&quot; started (read a few chapters), and &quot;well&quot; started (at least half way through).&lt;/li&gt;
&lt;li&gt;For those that were briefly started, I removed bookmarks, virtual or physical, and added them to the unopened pile. Basically, calling &lt;strong&gt;bankruptcy on the &quot;briefly&quot; started&lt;/strong&gt;. This cleared a lot of open loops. A lot.&lt;/li&gt;
&lt;li&gt;With the &quot;well&quot; started books I &lt;strong&gt;recorded them in OmniFocus&lt;/strong&gt;. This has helped me to keep conscious of how many books I have on the go. This ended up being four in total. The goal is to have no more than two in progress.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Since starting this two weeks ago, I have completed one book, and will finish the second this week. I will be at my goal of two in progress. Oh, and I haven&#39;t bought any new books in the last two weeks -- there have been a couple of occasions where I would have.&lt;/p&gt;&lt;img src=&quot;http://firsthand-blog.s3.amazonaws.com/2013/04/taming-the-unread-pile-of-books.png&quot; alt=&quot;Book Queue in OmniFocus&quot; width=&quot;453&quot; height=&quot;276&quot; border=&quot;0&quot; /&gt;&lt;p&gt;Yes, I know this all sounds pretty ridiculous. However, I bet I&#39;m not the only developer out there, with a book addiction. If you are, please let me know in the comments, how you have curbed your book buying behaviour, or please give my recovery plan a go!&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/5096608649281527367'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/5096608649281527367'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2013/04/taming-pile-of-unread-books.html' title='Taming the pile of unread books'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-5713757516393927361</id><published>2013-04-05T11:54:00.000-04:00</published><updated>2014-07-11T12:05:52.097-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="developer-challenge"/><title type='text'>April Developer Challenge: Feature Development With Pull Requests</title><content type='html'>&lt;p&gt;Note: This was originally posted to the &lt;a href=&quot;http://blog.godyanmo.com&quot;&gt;Dynamo Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This month&amp;#8217;s Dynamo Developer Challenge has been inspired by our own &lt;a href=&quot;https://github.com/DanielWright&quot;&gt;Daniel Wright&lt;/a&gt;—more about that in the moment.&lt;/p&gt;

&lt;p&gt;In a nutshell, for the month of April we will be experimenting across the studio with using &lt;a href=&quot;https://help.github.com/articles/using-pull-requests&quot;&gt;Pull Requests&lt;/a&gt; to develop a new features. We are moving beyond simply using them as a &lt;a href=&quot;/blog/2013/04/04/dynamo-developer-challenges-helping-us-to-improve-our-craft/&quot;&gt;Code Review tool&lt;/a&gt;, as we have in a past challenge.&lt;/p&gt;

&lt;p&gt;Over the last few months, Daniel has been religiously using Pull Requests to push new features. As I&amp;#8217;m a bit of GitHub stalker I love seeing this, as it gives me a chance to provide feedback on commits and putting Code Reviews into practice. However, these Pull Requests were created once the feature was deemed &amp;#8220;done.&amp;#8221;&lt;/p&gt;

&lt;p&gt;After viewing &lt;a href=&quot;http://zachholman.com/about&quot;&gt;Zach Holman&amp;#8217;s&lt;/a&gt; slides from a talk titled &lt;a href=&quot;https://speakerdeck.com/holman/github-behind-the-feature&quot;&gt;GitHub: Behind the Feature&lt;/a&gt;, Daniel began creating Pull Requests at the &lt;em&gt;start&lt;/em&gt; of a new feature. And I&amp;#8217;ve been impressed by what I have seen so far! But I don&amp;#8217;t want to get a head of myself; I&amp;#8217;ll share some observations at the end of this challenge.&lt;/p&gt;

&lt;p&gt;So, how does this all work?&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s some steps, based on the write-up Daniel did for his current project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choose a feature to implement, and create a new Git feature branch for it.&lt;/li&gt;
&lt;li&gt;Once you&amp;#8217;ve selected your feature to work on, you&amp;#8217;d create a new branch for it:
&lt;code&gt;git checkout -b features/your-new-feature&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Now do a very small amount of work, just enough that you can commit it. For example, you might create the view-template you&amp;#8217;re going to use (e.g. &lt;code&gt;app/views/pages/about.html.haml&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Now commit it!
&lt;code&gt;git add . &amp;amp;&amp;amp; git commit -m &quot;Adds about page template&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Push your branch up to GitHub:
&lt;code&gt;git push -u origin HEAD&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Finally, visit the project page on GitHub and create the pull request. Since you just pushed the branch, the project&amp;#8217;s landing-page should prompt you to create the pull request. Give it a descriptive title, and describe what you&amp;#8217;re planning to accomplish with the PR. For a simple integration job, this should be fairly straightforward, but you can be as descriptive as you like.&lt;/li&gt;
&lt;li&gt;Submit the pull request!&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;So, the April challenge has been posted for our Dynamo-Devs, but we encourage you to join us too. Are you up for the challenge? Please share you experiences in the comments along with our team&amp;#8217;s.&lt;/p&gt;

&lt;p&gt;For a little more background on this development strategy, checkout the slides below:&lt;/p&gt;

&lt;script async class=&quot;speakerdeck-embed&quot; data-id=&quot;058a431079f80130a8d9123138098c12&quot;
  data-ratio=&quot;1.77777777777778&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/5713757516393927361'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/5713757516393927361'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2013/04/april-developer-challenge-feature.html' title='April Developer Challenge: Feature Development With Pull Requests'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-978017353211823365</id><published>2013-04-04T11:50:00.000-04:00</published><updated>2014-07-11T12:05:02.301-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="developer-challenge"/><title type='text'>Developer Challenges: Helping Us to Improve Our Craft</title><content type='html'>&lt;p&gt;NOTE: This was originally posted to the &lt;a href=&quot;http://blog.godynamo.com/&quot;&gt;Dynamo Blog&lt;/a&gt;.

&lt;p&gt;We&amp;#8217;re sharing an initiative that we&amp;#8217;ve been experimenting off and on over the last year called &amp;#8220;Improving Your Craft&amp;#8221;, a.k.a Dynamo Developer Challenges.&lt;/p&gt;

&lt;p&gt;These began as weekly challenges to help the team members and the team as a whole to improve development practices and increase developer happiness. Admittedly, when I was first driving this initiative, I was infrequent in posting these challenges, and the weekly schedule was a little too ambitious. Based on feedback from the team, we reduced the frequency to a monthly schedule, and I&amp;#8217;m more disciplined in posting challenges each month—a calendar reminder really helps!&lt;/p&gt;

&lt;p&gt;Here are some examples of the challenges posted to date:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Self-Directed Morning Code Review&lt;/strong&gt;&lt;br/&gt;Inspired by Jason Fried&amp;#8217;s post &lt;a href=&quot;http://37signals.com/svn/posts/3048-morning-tells-the-truth&quot;&gt;Morning tells the truth&lt;/a&gt;, this challenge asked developers to review their commit log from the previous day as a self-directed code review.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pull Requests for Code Reviews&lt;/strong&gt;&lt;br/&gt;This time it was Zach Holman&amp;#8217;s talk &lt;a href=&quot;http://www.confreaks.com/videos/706-rubyconf2011-how-github-uses-github-to-build-github&quot;&gt;How GitHub Uses GitHub to Build GitHub&lt;/a&gt;. The driver for this challenge was to encourage developers to review each others code, pollinating knowledge across projects. If you&amp;#8217;re not currently using pull requests, &lt;a href=&quot;http://help.github.com/send-pull-requests/&quot;&gt;GitHub has some great documentation on the topic&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In-Person Peer Code Reviews&lt;/strong&gt;&lt;br/&gt;As an extension to the previous challenge, developers were asked to sit down with a peer for a 30-minute code walkthrough. It&amp;#8217;s amazing how much the author of the code learns by just walking someone else through it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automation&lt;/strong&gt;&lt;br/&gt;A final example was encouraged developers to start thinking what they can do to optimize their workflow. Too often we run the same set of commands everyday, when a simple shell alias can save us from repetitive typing or making a time-consuming mistake.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Hopefully this gives you a feel of the type of challenges that the team has been working on. And we would love if you joined us! Previously, these challenges have been posted to our Basecamp account, but we will now be posting them to the blog. I encourage you to share your experiences in the comments and the team will be sharing their as well, either as comments or blog posts (hint, hint!).&lt;/p&gt;

&lt;p&gt;Although I&amp;#8217;m a little late this month for April&amp;#8217;s challenge, please be on the lookout tomorrow.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/978017353211823365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/978017353211823365'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2013/04/developer-challenges-helping-us-to.html' title='Developer Challenges: Helping Us to Improve Our Craft'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-5097320118083898059</id><published>2012-11-30T16:55:00.001-05:00</published><updated>2013-12-10T21:53:19.178-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="vim"/><title type='text'>Have you tried ctags with Vim?</title><content type='html'>&lt;p&gt;After reading Mislav Marohnić&#39;s excellent post on &lt;a href=&quot;http://mislav.uniqpath.com/2011/12/vim-revisited/&quot;&gt;Vim&lt;/a&gt;, I decided to add ctags to my development environment. What does it buy you? It allows you to jump to method or class definitions with these commands:&lt;/p&gt;&lt;script src=&quot;https://gist.github.com/nicholasjhenry/7904431.js?file=1-mappings.txt&quot;&gt;&lt;/script&gt;&lt;br /&gt;
&lt;p&gt;Setup is pretty easy:&lt;/p&gt;&lt;script src=&quot;https://gist.github.com/nicholasjhenry/7904431.js?file=2-install.sh&quot;&gt;&lt;/script&gt;&lt;br /&gt;
&lt;p&gt;You can generate tags with:&lt;/p&gt;&lt;script src=&quot;https://gist.github.com/nicholasjhenry/7904431.js?file=3-ctags.sh&quot;&gt;&lt;/script&gt;&lt;br /&gt;
&lt;p&gt;But you probably won&#39;t want to do all that manually. As Mislav points out in his post, Tim Pope shows us how to &lt;a href=&quot;http://tbaggery.com/2011/08/08/effortless-ctags-with-git.html&quot;&gt;automate tag generation with git hooks&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I&#39;ve been using ctags this afternoon and already it has turned Vim into a completely different editor for me.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/5097320118083898059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/5097320118083898059'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2012/11/have-you-tried-ctags-with-vim.html' title='Have you tried ctags with Vim?'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-6729005645038881484</id><published>2012-11-12T14:09:00.001-05:00</published><updated>2012-11-13T11:32:54.583-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="google-site-search"/><title type='text'>Using Google Site Search for Content Sites: Things to Keep in Mind</title><content type='html'>&lt;p&gt;I&#39;ve used &lt;a href=&quot;http://www.google.com/enterprise/search/products_gss.html&quot;&gt;Google Site Search&lt;/a&gt; for a couple of unstructured content sites (opposed to applications or structured content such as catalogs) and pretty happy with it, but there a certainly some things you should be aware of before committing to this service:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The service&#39;s crawler works the same on Google.com. This means, it will only index publicly available pages that it can access. So you cannot use it on password-protected staging sites.&lt;/li&gt;&lt;li&gt;If you consider removing the password from the staging site you won&#39;t want to do that either, as your site must be registered with Google Webmaster tools, so your staging site will eventually end up in the Google.com index. But there&#39;s also another issue.&lt;/li&gt;&lt;li&gt;Indexes to URL&#39;s contain the domain of your site, so you can&#39;t index your staging site, then hope to use that index in your live site.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;If you&#39;re re-launching an existing site -- your only option is to enable search after you have made that site publicly available via the production domain. If it&#39;s a new site, and you have the option, make the site publicly available a couple of days before hand and index the site. Google Site Search provides on-demand indexing, updating the index within 24 hours.&lt;/p&gt;&lt;p&gt;When indexing the site, you have three options for supplying URL&#39;s:&lt;p&gt;&lt;ul&gt;&lt;li&gt;Individual URL&#39;s only&lt;/li&gt;&lt;li&gt;URL&#39;s linked from a specific page or Sitemap&lt;/li&gt;&lt;li&gt;URL&#39;s in a Sitemap only&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Again, you must have your site registered with &lt;a href=&quot;http://www.google.com/webmasters/tools/&quot;&gt;Google Webmaster Tools&lt;/a&gt; for the indexing to work.&lt;/p&gt;&lt;p&gt;For more information on indexing checkout &lt;a href=&quot;http://support.google.com/customsearch/bin/topic.py?hl=en&amp;topic=16792&amp;parent=&amp;ctx=topic&quot;&gt;Custom Search Help&lt;/a&gt; documentation.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/6729005645038881484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/6729005645038881484'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2012/11/using-google-site-search-for-content.html' title='Using Google Site Search for Content Sites: Things to Keep in Mind'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5548895711100825622.post-7718496753677180276</id><published>2012-10-26T18:48:00.001-04:00</published><updated>2012-10-26T18:49:10.497-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="domain-patterns"/><title type='text'>Domain Patterns are Alexandrian Patterns</title><content type='html'>&lt;p&gt;It&#39;s been a while since I have posted on this blog. So just to let you know that I&#39;m still alive, this is what has been keeping me occupied. It&#39;s best summed up by a quote from the book &lt;a href=&quot;http://www.amazon.com/Object-Thinking-DV-Microsoft-Professional-David/dp/0735619654&quot;&gt;Object Thinking&lt;/a&gt; by David West. This is a must read for any Rails developer who is following the object-oriented Rails culture.&lt;/p&gt;&lt;blockquote&gt;Patterns most useful to object thinkers should be derived from the problem domain, just as objects are. They should facilitate thinking about co-ordination and scripting of objects or about useful ways of assembling objects into components or applications. They could be considered Alexandrian patterns. Few of the patterns (about 6 of the 23) presented in the GoF book satisfy this demand. Martin Fowler’s book on Analysis Patterns presents examples derived from a domain and is much closer to Alexander’s intent than the GoF book.&lt;/blockquote&gt;&lt;p&gt;My intent is to post more on Domain Patterns in a Rails context in the near future. We&#39;ll see.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/7718496753677180276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5548895711100825622/posts/default/7718496753677180276'/><link rel='alternate' type='text/html' href='http://blog.firsthand.ca/2012/10/domain-patterns-are-alexandrian-patterns.html' title='Domain Patterns are Alexandrian Patterns'/><author><name>Nicholas Henry</name><uri>http://www.blogger.com/profile/14291733277357950382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry></feed>