<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Pacifica Labs Blog</title><link>https://www.pacificalabs.org/blog/</link><description>Notes from building, modernising and running production software, by Tarun Mookhey.</description><language>en-au</language><atom:link href="https://www.pacificalabs.org/blog/index.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Tue, 06 Oct 2026 00:00:00 +0000</lastBuildDate><item><title>Designing API integrations for the day the other system fails</title><link>https://www.pacificalabs.org/blog/designing-api-integrations-for-the-day-the-other-system-fails/</link><guid isPermaLink="true">https://www.pacificalabs.org/blog/designing-api-integrations-for-the-day-the-other-system-fails/</guid><pubDate>Tue, 06 Oct 2026 00:00:00 +0000</pubDate><dc:creator>Tarun Mookhey</dc:creator><category>Systems &amp; Integrations</category><description>Source of truth, retries, idempotency, webhooks, reconciliation and observability: the parts of an API integration that decide whether it holds up in production.</description><content:encoded><![CDATA[<p>Most integrations are demonstrated on the happy path: call the API, get a response, move on. In production, the other system will eventually be slow, unavailable, rate-limited or simply wrong. An integration is not finished until it has a defined behaviour for each of those days.</p>
<h2 id="decide-who-owns-each-piece-of-data">Decide who owns each piece of data</h2>
<p>For every object that moves between systems, decide which one is the source of truth, and in which direction changes flow. Two systems that both believe they own a customer record will disagree sooner or later. Writing the ownership down before building anything removes a whole category of later argument.</p>
<h2 id="authentication-is-part-of-the-design">Authentication is part of the design</h2>
<p>Integrations act as someone: a service account, or the user. That choice affects permissions, audit trails and what happens when a token expires or is revoked. OAuth2-connected user accounts, for example, need a plan for refresh failures and for users who disconnect.</p>
<h2 id="webhooks-and-polling">Webhooks and polling</h2>
<p>Webhooks are timely but unreliable on their own: deliveries can be missed, delayed, duplicated or arrive out of order. Polling is slower but easy to reason about. Many robust integrations use both: webhooks for speed, a periodic poll to catch what was missed.</p>
<h2 id="retries-need-idempotency">Retries need idempotency</h2>
<p>Retrying a failed call is only safe if repeating it cannot do harm. Give each operation a stable identifier so that sending it twice has the same effect as sending it once, and back off between attempts so a struggling system is not made worse. Decide when to stop retrying and where the failed item goes instead.</p>
<h2 id="expect-duplicates-and-partial-failure">Expect duplicates and partial failure</h2>
<p>Assume the same event can arrive more than once, and that a multi-step operation can succeed in the middle and fail at the end. Design each step so it can be repeated, and record enough state to resume.</p>
<h2 id="plan-reconciliation">Plan reconciliation</h2>
<p>However careful the design, systems drift. A scheduled reconciliation that compares the two sides and reports (or repairs) differences turns silent corruption into a visible, fixable item.</p>
<h2 id="respect-limits-and-make-failure-visible">Respect limits, and make failure visible</h2>
<p>Rate limits, quotas and timeouts are part of the contract. Build in throttling, and make failures observable: structured logging, alerting, and a way for someone to see what is stuck and retry it by hand. A manual recovery path is not a sign of weakness; it is what makes the automated path trustworthy.</p>
<h2 id="a-checklist">A checklist</h2>
<ul>
<li>Source of truth defined for each object</li>
<li>Authentication and token failure handled</li>
<li>Webhooks backed by polling or reconciliation</li>
<li>Idempotent operations with back-off</li>
<li>A place for items that keep failing</li>
<li>Monitoring and a manual recovery path</li>
</ul>
]]></content:encoded></item><item><title>How to modernise a legacy Rails application without rewriting the business</title><link>https://www.pacificalabs.org/blog/modernise-legacy-rails-without-rewriting-the-business/</link><guid isPermaLink="true">https://www.pacificalabs.org/blog/modernise-legacy-rails-without-rewriting-the-business/</guid><pubDate>Tue, 06 Oct 2026 00:00:00 +0000</pubDate><dc:creator>Tarun Mookhey</dc:creator><category>Engineering</category><description>A practical framework for deciding between a staged Rails upgrade and a rewrite, drawing on a Rails 2/Merb to Rails 7.1 modernisation.</description><content:encoded><![CDATA[<p>A legacy application is rarely risky because it is old. It is risky because the framework, runtime, data layer and operating system underneath it have stopped receiving fixes, while the business behaviour on top of it still matters every day. A rewrite treats those two things as one problem. Staged modernisation treats them as two.</p>
<h2 id="start-by-separating-the-stack-from-the-behaviour">Start by separating the stack from the behaviour</h2>
<p>Before choosing between an upgrade and a rewrite, write down two lists.</p>
<p><strong>What is obsolete:</strong> the framework version, the Ruby runtime, the ORM or data layer, unsupported gems, the operating system, deployment steps that live in one person&rsquo;s head.</p>
<p><strong>What is valuable:</strong> the rules, edge cases and workflows that years of production use have taught the application. These are usually undocumented, and they are the part a rewrite is most likely to lose.</p>
<p>If the second list is long and the first is the real source of risk, an incremental path is usually the lower-risk answer.</p>
<h2 id="when-incremental-modernisation-is-viable">When incremental modernisation is viable</h2>
<p>Staged upgrades tend to work when:</p>
<ul>
<li>the application still runs and is understood well enough to be tested;</li>
<li>the business logic is worth keeping;</li>
<li>the obsolete layers can be replaced one at a time;</li>
<li>the team can keep shipping while the work happens.</li>
</ul>
<p>A programme that moved a Rails 2/Merb application to Rails 7.1 is an example of the shape this takes: framework, Ruby runtime (1.9 to 3.3), data layer (DataMapper to ActiveRecord) and operating system (Ubuntu 10 to 22.04) were each moved on their own terms rather than in one big-bang cutover. You can read the details in the <a href="/work/legacy-rails-modernisation/"



 


>case study</a>.</p>
<h2 id="get-test-safety-before-you-change-anything">Get test safety before you change anything</h2>
<p>The most useful early work is often unglamorous: characterise how the application behaves today. Even a thin layer of tests around the workflows that matter lets you tell the difference between &ldquo;the upgrade broke something&rdquo; and &ldquo;it always did that&rdquo;. Without it, every later step is a leap of faith.</p>
<h2 id="sequence-the-layers-deliberately">Sequence the layers deliberately</h2>
<p>Order matters because the layers depend on each other.</p>
<ol>
<li><strong>Runtime and dependencies first, where possible.</strong> Move to a supported Ruby and replace abandoned gems so later steps are not blocked.</li>
<li><strong>Framework in steps.</strong> Major Rails versions have documented upgrade paths; take them one version at a time rather than jumping.</li>
<li><strong>Data layer when you can isolate it.</strong> Swapping an ORM touches every query. Do it behind tests, and ideally not in the same release as a framework change.</li>
<li><strong>Infrastructure alongside, not after.</strong> Operating-system and deployment changes are coupled to the runtime, so plan them together.</li>
</ol>
<p>Keep every step observable and reversible. If a step cannot be rolled back, make it smaller.</p>
<h2 id="when-a-rewrite-is-justified">When a rewrite is justified</h2>
<p>Sometimes it is. A rewrite makes sense when the business behaviour itself is changing, when the existing logic is not worth preserving, or when the cost of understanding the old system exceeds the cost of rebuilding it. The point is that this is a business-risk decision, not a preference for newer tools.</p>
<h2 id="a-quick-test">A quick test</h2>
<p>Ask: <em>if we replaced everything at once, what would we have no way to verify?</em> If the answer is &ldquo;most of what the business relies on&rdquo;, staged modernisation is probably the safer route.</p>
]]></content:encoded></item><item><title>Where AI belongs in business software — and where deterministic code should win</title><link>https://www.pacificalabs.org/blog/where-ai-belongs-in-business-software/</link><guid isPermaLink="true">https://www.pacificalabs.org/blog/where-ai-belongs-in-business-software/</guid><pubDate>Tue, 06 Oct 2026 00:00:00 +0000</pubDate><dc:creator>Tarun Mookhey</dc:creator><category>AI</category><description>A practical boundary between deterministic software and AI features in business applications, with a decision test for each workflow.</description><content:encoded><![CDATA[<p>AI is useful when it makes a workflow faster, a search better, a decision clearer or a product easier to use. It is not a reason to replace reliable, deterministic software with uncertainty. The practical question for any feature is not &ldquo;can AI do this?&rdquo; but &ldquo;should the answer be exact, or is a useful approximation acceptable?&rdquo;</p>
<h2 id="keep-deterministic-code-for-what-must-be-exact">Keep deterministic code for what must be exact</h2>
<p>Use ordinary code where correctness is binary or auditable:</p>
<ul>
<li>calculations and totals;</li>
<li>permissions and access control;</li>
<li>money movement;</li>
<li>hard business rules;</li>
<li>compliance logic where exactness is required.</li>
</ul>
<p>These have right and wrong answers, and the system needs to give the same answer every time. Probabilistic behaviour here is a defect, not a feature.</p>
<h2 id="consider-ai-where-meaning-is-ambiguous">Consider AI where meaning is ambiguous</h2>
<p>AI earns its place where the input is language or the output is a judgement call:</p>
<ul>
<li>understanding free-text requests;</li>
<li>semantic ranking and search;</li>
<li>summarising long material;</li>
<li>classifying messages or documents;</li>
<li>recommending from many options;</li>
<li>drafting text for a person to review.</li>
</ul>
<h2 id="put-a-human-in-the-loop-where-it-matters">Put a human in the loop where it matters</h2>
<p>Assistance that a user can review is far safer than automation that acts unseen. Draft, suggest and rank; let a person approve anything with consequences. Design the review step as part of the feature rather than an afterthought, and decide in advance how you will check the output is good enough.</p>
<h2 id="search-is-often-the-practical-starting-point">Search is often the practical starting point</h2>
<p>Many business problems that sound like &ldquo;we need AI&rdquo; are really search problems. Combining conventional text matching with semantic (vector) search can help people find the right record quickly while the underlying data and rules remain deterministic. TickMessage, for example, uses trigram, full-text and vector search in PostgreSQL to find the right contact quickly — a search improvement, with the messaging logic itself remaining ordinary, testable code.</p>
<h2 id="a-decision-test">A decision test</h2>
<p>For each workflow, ask:</p>
<ol>
<li>Is there a single correct answer? If yes, use deterministic code.</li>
<li>Is the input ambiguous or linguistic? If yes, AI may help.</li>
<li>Can a person review the result before it matters? If not, be cautious.</li>
<li>How will we know it is working? If there is no answer, there is no feature yet.</li>
</ol>
]]></content:encoded></item><item><title>The software after checkout: connecting ecommerce to inventory, suppliers and delivery</title><link>https://www.pacificalabs.org/blog/the-software-after-checkout-connecting-ecommerce-to-inventory-suppliers-and-delivery/</link><guid isPermaLink="true">https://www.pacificalabs.org/blog/the-software-after-checkout-connecting-ecommerce-to-inventory-suppliers-and-delivery/</guid><pubDate>Mon, 05 Oct 2026 00:00:00 +0000</pubDate><dc:creator>Tarun Mookhey</dc:creator><category>Operations</category><description>In operational ecommerce the hard part starts after payment: stock, purchasing, fulfilment and delivery have to stay consistent.</description><content:encoded><![CDATA[<p>A storefront can be built quickly. What determines whether the business runs well is what happens once the customer has paid.</p>
<h2 id="the-order-is-a-promise">The order is a promise</h2>
<p>At checkout, the system promises something: these items, available, delivered by this time. Whether it can keep that promise depends on stock that may be perishable, suppliers with their own lead times, a fulfilment process, and a delivery route. If those live in separate tools joined by spreadsheets, the promise is only as good as the last person who updated them.</p>
<h2 id="where-the-gaps-appear">Where the gaps appear</h2>
<p>Typical failure points are predictable: stock counts that lag reality, supplier orders raised by hand, delivery plans built from an export, and finance entering the same transaction twice. Each gap is small. Together they are the operation&rsquo;s real cost.</p>
<h2 id="connect-the-lifecycle-not-just-the-systems">Connect the lifecycle, not just the systems</h2>
<p>The useful framing is a single order lifecycle that stock, purchasing, fulfilment, delivery, finance and customer service all read from and write to. Integrations then stop being add-ons and become how the operation expresses itself. An order changes state and the rest of the business can respond.</p>
<h2 id="design-the-boundaries">Design the boundaries</h2>
<p>Not everything belongs in one platform. Accounting stays in the accounting system, route planning in the route planner. The engineering work is the boundary: what data moves, when, how exceptions are handled, and how both sides are reconciled.</p>
<h2 id="make-exceptions-visible">Make exceptions visible</h2>
<p>Out-of-stock substitutions, failed deliveries and supplier shortfalls are normal. A good system surfaces them to the people who can act, instead of hiding them until the customer calls.</p>
<p>This is the pattern behind our <a href="/work/ecommerce-fulfilment-platform/"



 


>ecommerce and operations work</a> and the <a href="/industries/ecommerce/#after-checkout"



 


>ecommerce industry approach</a>. If the difficult part of your system happens after checkout, <a href="/contact/?type=integration"



 


>talk to us about the workflow</a>.</p>
]]></content:encoded></item><item><title>When Data Lies: Election Forecasts and Ecommerce Tech</title><link>https://www.pacificalabs.org/blog/when-data-lies-election-forecasts-and-ecommerce-tech/</link><guid isPermaLink="true">https://www.pacificalabs.org/blog/when-data-lies-election-forecasts-and-ecommerce-tech/</guid><pubDate>Sat, 23 Nov 2024 05:00:00 +0000</pubDate><dc:creator>Tarun Mookhey</dc:creator><category>Operations</category><description>What election forecast failures teach us about data quality in ecommerce.</description><content:encoded><![CDATA[<p>Did the 2024 US election result come as a surprise to you? If so you may be shocked to learn the last 3 US elections were inaccurately forecast, not to mention the last 2 UK elections - and the last 3 Australian elections.</p>
<h3 id="why-this-matters"><em><strong>Why this matters:</strong></em></h3>
<p>If sophisticated polling operations with billion-dollar budgets can misread consumer sentiment so drastically across the US, UK, and Australia, it raises critical questions about the reliability of our own data-driven ecommerce systems.</p>
<p>Consider this: The last three US elections, two UK elections, and three Australian elections all saw significant forecasting failures. These aren&rsquo;t just political mishaps – they&rsquo;re warnings about the fragility of predictive systems that mirror our own ecommerce technology stacks.</p>
<p>Modern ecommerce operations share remarkable similarities with election campaign infrastructure:</p>
<ul>
<li>Both leverage recommendation engines for programmatic ad buying</li>
<li>Both rely on A/B testing to optimize user journeys</li>
<li>Both deploy sophisticated content personalization with behavioral triggers</li>
</ul>
<p>The decision-making technology powering these systems isn&rsquo;t just similar – it&rsquo;s often identical. This parallel should give us pause.</p>
<h3 id="what-you-can-do"><em><strong>What You Can Do:</strong></em></h3>
<p>As we approach the critical XMAS buying season, now is the perfect time to conduct a thorough review of your data-driven processes. Gather your team and suppliers for a comprehensive tech stack assessment. Remember: in ecommerce, faulty data doesn&rsquo;t just impact your bottom line – it can be an extinction-level event for your business.</p>
<h3 id="appendix"><em><strong>Appendix</strong></em></h3>
<ol>
<li><em>The parallels between political polling and ecommerce analytics are striking. Both attempt to predict human behavior through data analysis, and both can fail spectacularly when their underlying assumptions are flawed.</em></li>
<li><em>For ecommerce businesses, the stakes are arguably higher than political polls. While a failed election forecast might embarrass pollsters, failed ecommerce predictions directly impact revenue and can lead to business failure.</em></li>
</ol>
]]></content:encoded></item><item><title>How to use Procfile for Ruby on Rails apps</title><link>https://www.pacificalabs.org/blog/how-to-use-procfile/</link><guid isPermaLink="true">https://www.pacificalabs.org/blog/how-to-use-procfile/</guid><pubDate>Sat, 13 Jul 2024 05:00:00 +0000</pubDate><dc:creator>Lee Sheppard</dc:creator><category>Engineering</category><description>Understanding the value of using the Procfile in the Rails apps.</description><content:encoded><![CDATA[<p>A Procfile is a text file used in Ruby on Rails applications to define the various processes that make up the application. Each line in the Procfile specifies a process type and the command used to run that process. Procfiles are commonly used with process management tools like Foreman, which can read the Procfile and start the specified processes. There are many hosting services that now utilise this type of file to operate your applications with.</p>
<p>Here&rsquo;s an example of how to write a Procfile correctly for a Ruby on Rails application:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#e6db74">web</span>: bundle exec rails server <span style="color:#f92672">-</span>p <span style="color:#ae81ff">3000</span>
</span></span><span style="display:flex;"><span><span style="color:#e6db74">worker</span>: bundle exec rake <span style="color:#e6db74">jobs</span>:work
</span></span></code></pre></div><p>Let&rsquo;s break down each part of this Procfile:</p>
<ol>
<li>
<p><code>web</code>: This line specifies the process type, in this case, it&rsquo;s the web server process. When you run this line through a process management tool, it will start the web server for your Rails application.</p>
</li>
<li>
<p><code>bundle exec rails server</code>: This is the command to run the web server process. It uses the <code>bundle exec</code> prefix to ensure that the Rails server is executed within the context of the application&rsquo;s dependencies managed by Bundler.</p>
</li>
<li>
<p><code>worker</code>: This line specifies another process type, in this case, it&rsquo;s a worker process. Worker processes are often used for background jobs, and this line tells the process management tool to start the worker process.</p>
</li>
<li>
<p><code>bundle exec rake jobs:work</code>: This is the command to run the worker process. It uses the <code>bundle exec</code> prefix just like the web server command to ensure that the worker process is executed within the application&rsquo;s context.</p>
</li>
</ol>
<p>When you have a Procfile set up with these lines, you can use process management tools like Foreman to start all the processes defined in the Procfile with a single command. This can be especially useful in development environments to mimic the environment in which the application will run in production.</p>
<p>The names of each process (e.g. web, worker) can be customised to suit your preferences, these titles are seen in your terminal output and as such are used to identify what processes are running or have failed.</p>
<p>Further, you can have a Procfile.dev in your application to run processes specific to local development environments. A new Rails application (version 7) with initial configuration set up to use Yarn/ESBuild/TailwindCSS would typically have a Procfile.dev that looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#e6db74">web</span>: bin<span style="color:#f92672">/</span>rails server <span style="color:#f92672">-</span>p <span style="color:#ae81ff">3000</span>
</span></span><span style="display:flex;"><span><span style="color:#e6db74">js</span>: yarn build <span style="color:#f92672">--</span>watch
</span></span><span style="display:flex;"><span><span style="color:#e6db74">css</span>: yarn <span style="color:#e6db74">build</span>:css <span style="color:#f92672">--</span>watch
</span></span></code></pre></div><p>A separate script would be required to run this Procfile locally of which you can place in the <strong>bin</strong> folder. The standard practice is to have a script named <strong>dev</strong> in this folder which would contain the following:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#75715e">#!/usr/bin/env sh
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> ! gem list foreman -i --silent; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;Installing foreman...&#34;</span>
</span></span><span style="display:flex;"><span>  gem install foreman
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>exec foreman start -f Procfile.dev <span style="color:#e6db74">&#34;</span>$@<span style="color:#e6db74">&#34;</span>
</span></span></code></pre></div><p>Now when you run the <strong>bin/dev</strong> from the command line your processes will all start up using Foreman.</p>
<p>An alternative configuration for Rails developers is to optimise the operation of their apps using the Puma server. You can use the config file by using this line in the Procfile for reference:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#e6db74">web</span>: bundle exec puma <span style="color:#f92672">-</span>C <span style="color:#f92672">.</span>/config<span style="color:#f92672">/</span>puma<span style="color:#f92672">.</span>rb
</span></span></code></pre></div><p>In summary, a Procfile in Ruby on Rails is a simple yet powerful way to manage multiple processes within your application. It allows you to define process types and their respective commands, making it easier to start and manage different parts of your application.</p>
]]></content:encoded></item><item><title>Bash Keyboard Shortcuts Every Software Engineer Should Know</title><link>https://www.pacificalabs.org/blog/bash-keyboard-shortcuts/</link><guid isPermaLink="true">https://www.pacificalabs.org/blog/bash-keyboard-shortcuts/</guid><pubDate>Fri, 18 Aug 2023 00:00:00 +0000</pubDate><dc:creator>Pacifica Labs</dc:creator><category>Engineering</category><description>16 essential keyboard shortcuts for Bash</description><content:encoded><![CDATA[<h3 id="why-it-matters">Why it matters:</h3>
<p>For any software engineer of note, your time is always at a premium, so the ability to quickly &amp; efficiently navigate your way around the terminal will boost your productivity no end.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>ctrl + A
</span></span><span style="display:flex;"><span><span style="color:#75715e">#go to the START of the current line</span>
</span></span><span style="display:flex;"><span>ctrl + E
</span></span><span style="display:flex;"><span><span style="color:#75715e">#go to the END of the current line</span>
</span></span><span style="display:flex;"><span>ctrl + L
</span></span><span style="display:flex;"><span><span style="color:#75715e">#clear the screen</span>
</span></span><span style="display:flex;"><span>ctrl + U
</span></span><span style="display:flex;"><span><span style="color:#75715e">#clear the line BEFORE the cursor position</span>
</span></span><span style="display:flex;"><span>ctrl + K
</span></span><span style="display:flex;"><span><span style="color:#75715e">#clear the line AFTER the cursor position</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#NB If you are at the end of the line the entire line is cleared</span>
</span></span><span style="display:flex;"><span>alt + F
</span></span><span style="display:flex;"><span><span style="color:#75715e">#move forward one word position</span>
</span></span><span style="display:flex;"><span>alt + B
</span></span><span style="display:flex;"><span><span style="color:#75715e">#move backwards one word position</span>
</span></span><span style="display:flex;"><span>tab
</span></span><span style="display:flex;"><span><span style="color:#75715e">#autocomplete file &amp; folder names...based on existing folder contents</span>
</span></span></code></pre></div><h3 id="the-big-picture">The Big Picture:</h3>
<p><em>Remember these venerable shortcuts?</em></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>CTRL-C <span style="color:#66d9ef">for</span> COPY
</span></span><span style="display:flex;"><span>CTRL-X <span style="color:#66d9ef">for</span> CUT
</span></span><span style="display:flex;"><span>CTRL-V <span style="color:#66d9ef">for</span> PASTE
</span></span><span style="display:flex;"><span>CTRL-Z <span style="color:#66d9ef">for</span> UNDO
</span></span></code></pre></div><p>Of course you do, you use them daily.</p>
<p>Similarly, once you practice bash shortcuts they will speed your navigation &amp; boost productivity x 100</p>
<h3 id="go-deeper">Go Deeper&hellip;</h3>
<p><em>Further Reading:</em></p>
<p><a href="www.redhat.com/sysadmin/shortcuts-command-line-navigation"



 


>RedHatDotCom: 5 ways to navigate the Linux terminal faster </a></p>
]]></content:encoded></item><item><title>Has and Belongs To Many (Headaches)</title><link>https://www.pacificalabs.org/blog/has-and-belongs-to-many/</link><guid isPermaLink="true">https://www.pacificalabs.org/blog/has-and-belongs-to-many/</guid><pubDate>Wed, 02 Mar 2022 05:00:00 +0000</pubDate><dc:creator>Tarun Mookhey</dc:creator><category>Engineering</category><description>We provide tips to make the setup of HABTM associations painfree.</description><content:encoded><![CDATA[<p>The HABTM association is often confusing and can lead to frustration if defined incorrectly. Here find instructions on how to set it correctly.</p>
<h3 id="why-this-matters"><em><strong>Why this matters:</strong></em></h3>
<p>One of the more complicated associations&hellip;..</p>
<p>ActiveRecord requires you to <a href="https://www.pacificalabs.org/blog/has-and-belongs-to-many/#appendix"


 title="1"


 


>*define</a> the relationships between two classes.
Whilst the <em>has_many</em> and <em>belongs_to</em> association methods attract the most attention<a href="https://www.pacificalabs.org/blog/has-and-belongs-to-many/#1"


 title="1"


 


>*</a>, let&rsquo;s consider the more obscure <em>has_and_belongs_to_many</em>.</p>
<h3 id="appendix"><em><strong>Appendix</strong></em></h3>
<ol>
<li>
<p><em>BTW Did anyone tell you that software development requires you to spend an insane amount of time thinking of the nature of things in the world and their interrelationships? All in the name of data modelling.</em></p>
</li>
<li>
<p><em>And let&rsquo;s admit, especially for beginners, newbies for those rusty on ActiveRecord Associations, we&rsquo;ll be tempted to try and jury-rig as many relationships into this association and make it work.</em></p>
</li>
</ol>
]]></content:encoded></item><item><title>Step-By-Step-Guide: Deploy your Hugo-built static site online.</title><link>https://www.pacificalabs.org/blog/tips-on-deploying-static-sites-built-with-hugo/</link><guid isPermaLink="true">https://www.pacificalabs.org/blog/tips-on-deploying-static-sites-built-with-hugo/</guid><pubDate>Thu, 22 Jul 2021 05:00:00 +0000</pubDate><dc:creator>Tarun Mookhey</dc:creator><category>Engineering</category><description>Follow these straightforward steps to deploy your static site built with Hugo for free.</description><content:encoded><![CDATA[<p>When selecting a static site generator our team were frustrated with the slow build time of Jekyll.</p>
<p>We eventually settled upon <a href="https://www.gohugo.com"




 target="_blank"
 


>Hugo</a>, the superfast framework built in Googles own language Go.</p>
<p>The motto of Hugo is build sites lightning fast &amp; the <a href="https://stackshare.io/stackups/hugo-vs-jekyll#:~:text=Generally%20speaking%2C%20Hugo%20builds%20sites,is%20to%20stay%20extremely%20fast."




 target="_blank"
 


>build time</a> doesn&rsquo;t disappoint.</p>
<p><em>Deploying static sites are not at all straightforward &amp; the options on the Hugo website don&rsquo;t really offer anything that&rsquo;s fast to setup &amp; user friendly to maintain. Below is our guide to quickly deploying your Hugo site&hellip;.</em></p>
<h3 id="assumptions--prerequisites">Assumptions &amp; Prerequisites</h3>
<ol>
<li>You have Hugo installed</li>
<li>You&rsquo;re ready to publish your content online.</li>
<li>You have initialized your root folder with git &amp; have made a number of commitments.</li>
</ol>
<h3 id="steps">Steps:</h3>
<ol>
<li>Ensure your baseURL is an empty string and not a url.</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># config.yaml</span>
</span></span><span style="display:flex;"><span>title: <span style="color:#e6db74">&#34;Pacifica Labs&#34;</span>
</span></span><span style="display:flex;"><span>baseURL: <span style="color:#e6db74">&#34;&#34;</span>  <span style="color:#75715e"># note the absence of any url</span>
</span></span><span style="display:flex;"><span>languageCode: <span style="color:#e6db74">&#34;en-AU&#34;</span>
</span></span></code></pre></div><ol start="2">
<li>Ensure Hugo builds all your content from scratch by removing your public folder:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>rm -rf public/
</span></span></code></pre></div><ol start="3">
<li><em>Build your static site content</em>&hellip;</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ hugo
</span></span><span style="display:flex;"><span>Start building sites …
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>                   | EN
</span></span><span style="display:flex;"><span>-------------------+-----
</span></span><span style="display:flex;"><span>  Pages            | <span style="color:#ae81ff">21</span>
</span></span><span style="display:flex;"><span>  Paginator pages  |  <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>  Non-page files   |  <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>  Static files     | <span style="color:#ae81ff">18</span>
</span></span><span style="display:flex;"><span>  Processed images | <span style="color:#ae81ff">16</span>
</span></span><span style="display:flex;"><span>  Aliases          |  <span style="color:#ae81ff">6</span>
</span></span><span style="display:flex;"><span>  Sitemaps         |  <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>  Cleaned          |  <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Total in <span style="color:#ae81ff">263</span> ms
</span></span></code></pre></div><ol start="3">
<li>You will see newly compiled content in the <em>public</em> folder:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>$ ls public/
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>404.html
</span></span><span style="display:flex;"><span>about
</span></span><span style="display:flex;"><span>articles
</span></span><span style="display:flex;"><span>blog
</span></span><span style="display:flex;"><span>docs
</span></span><span style="display:flex;"><span>favicon.ico
</span></span><span style="display:flex;"><span>fonts
</span></span><span style="display:flex;"><span>gallery
</span></span><span style="display:flex;"><span>index.html
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>...<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>...<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>...<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>etc<span style="color:#f92672">)</span>
</span></span></code></pre></div><ol start="4">
<li>Create an empty repository on <a href="https://docs.github.com/en/get-started/quickstart/create-a-repo"




 target="_blank"
 


>github</a> and commit your entire project folder:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>git add .
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#e6db74">&#34;first commit&#34;</span>
</span></span></code></pre></div><ol start="5">
<li>
<p>Create a new branch called gh-pages which is the branch github pages will read from when deploying the static site:</p>
</li>
<li>
<p>Create a subtree</p>
</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git push origin <span style="color:#e6db74">`</span>git subtree split --prefix public master<span style="color:#e6db74">`</span>:gh-pages --force
</span></span></code></pre></div><ol start="7">
<li>
<p>Wait til the pages notification changes from <em>blue</em> to <em>green</em></p>
</li>
<li>
<p>Confirm your changes!</p>
</li>
</ol>
<h4 id="the-big-picture">The Big Picture:</h4>
<p>Key steps in deploying a Hugo repository require subtree usage.</p>
<h4 id="go-deeper">Go Deeper&hellip;</h4>
<p>(Further reading links here)
This is a <a href="https://gist.github.com/pacificalabs/27b60e18d0c1a472d6f7cde1350cde15"




 target="_blank"
 


>bash script</a> I have written to automate the above steps of the deployment process.</p>
<h4 id="appendix"><em><strong>Appendix</strong></em></h4>
<ol>
<li>The <a href="https://jamstack.org/generators/"




 target="_blank"
 


>top 4</a> global static site generators were Next.js, Hugo &amp; Gatsby &amp; Jekyll.</li>
<li>In benchmarking tests Hugo compiled <a href="https://forestry.io/blog/hugo-vs-jekyll-benchmark/#tl-dr"




 target="_blank"
 


>23x</a> faster than Jekyll.</li>
</ol>
]]></content:encoded></item></channel></rss>