<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Mike Coutermarsh</title>
    <description>The latest articles on Forem by Mike Coutermarsh (@mscccc).</description>
    <link>https://forem.com/mscccc</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F430%2Fc939518e-c271-47d8-83a4-4899b6764863.jpg</url>
      <title>Forem: Mike Coutermarsh</title>
      <link>https://forem.com/mscccc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mscccc"/>
    <language>en</language>
    <item>
      <title>How we use "ship small" to rapidly build new features at GitHub</title>
      <dc:creator>Mike Coutermarsh</dc:creator>
      <pubDate>Wed, 01 Jan 2020 23:55:26 +0000</pubDate>
      <link>https://forem.com/mscccc/how-we-use-ship-small-to-rapidly-build-new-features-at-github-5cl9</link>
      <guid>https://forem.com/mscccc/how-we-use-ship-small-to-rapidly-build-new-features-at-github-5cl9</guid>
      <description>&lt;p&gt;"Ship small! fast!" and "ship to learn!"&lt;/p&gt;

&lt;p&gt;You've seen that shouted everywhere on Twitter. But what does it actually look like in practice?&lt;/p&gt;

&lt;p&gt;I'm on the &lt;a href="https://github.com/features/actions"&gt;GitHub Actions&lt;/a&gt; team and we "ship small" every day to build new features quickly. Personally, this is my favorite way of building software. In this post I'll show you how we do it. &lt;/p&gt;

&lt;h2&gt;
  
  
  Let's build a new feature
&lt;/h2&gt;

&lt;p&gt;In this post we will pretend we are building a new feature for a web app. It has a complex UI + backend and will take a small team roughly 6 weeks to build.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project planning, define the minimal scope
&lt;/h2&gt;

&lt;p&gt;To start, the lead engineer, product manager and eng manager collaborate to define minimal scope. We determine what parts are a MUST for this new feature to be valuable to users.&lt;/p&gt;

&lt;p&gt;The lead engineer then does a break down of tasks and prioritizes them on a project board. Their job here isn't to be the person that figures out every technical detail. Their job is to find enough info to break the project up into small enough pieces people can get started with.&lt;/p&gt;

&lt;p&gt;During planning we aren't spending hours hammering out small details. Perfect upfront planning can be the enemy of shipping. We know that as long as we have the minimal scope defined, we can always iterate and improve from there. Software is never complete.&lt;/p&gt;

&lt;p&gt;There will still be things to figure out, but we don't need to wait to get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start writing code
&lt;/h2&gt;

&lt;p&gt;Getting started as soon as possible is important. I've never seen any software project go exactly to plan, as soon as code starts to be written, we know we will uncover new information that may change our approach.&lt;/p&gt;

&lt;p&gt;We need to be flexible and roll with it as we learn more. As individuals find problems, they document them in new issues and it gets added to the project plan.&lt;/p&gt;

&lt;h3&gt;
  
  
  The first pull request: the boilerplate
&lt;/h3&gt;

&lt;p&gt;Since this feature has a UI. One engineer will do the boilerplate setup for it. This is a blank page, that has a URL and is behind a feature flag. It's essentially a "hello, world" for the feature.&lt;/p&gt;

&lt;p&gt;This should be a very quick task. They will open the pull request, tag everyone else working on the feature, and we get it shipped to production. Everyone on the team gets added to the feature flag, they can now see the blank page in production.&lt;/p&gt;

&lt;p&gt;I &lt;strong&gt;cannot emphasize enough how important this first pull request is&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Once it's merged we've now made it much easier for others to build on top of it without running into each other. If your goal is to "ship small", I believe it's critical to start the project off that way as well. The first change is the example set for the changes to come after it. It's now culturally accepted to be shipping things to production&lt;br&gt;
that aren't complete yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We can now have parallel work streams:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 engineer can start working on the backend that feeds data to this page.&lt;/li&gt;
&lt;li&gt;Another engineer can start working on the frontend. &lt;/li&gt;
&lt;li&gt;The designer works on the UI. If they can code, they jump in and write markup + CSS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We now have everyone able to contribute and we're able to ship partially completed work to production confidently (remember, it's behind a flag).&lt;/p&gt;

&lt;p&gt;As small pieces of work are completed, everyone is opening pull requests, getting reviews from each other and merging to production. The shared context of the project is high.&lt;/p&gt;

&lt;p&gt;If we need reviews from other teams (security for example), these small PR's are fairly low effort to review for outside teams. Making it likely we get feedback faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is important because:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it allows people to work async (we are remote/different timezones).&lt;/li&gt;
&lt;li&gt;each pull request is small and reviewed by everyone else. Making them easy to review and keeping everyone aware of progress/context&lt;/li&gt;
&lt;li&gt;Project stakeholders can get feature flagged in and view production to see progress (and give feedback!)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Never get blocked, start ASAP
&lt;/h3&gt;

&lt;p&gt;Often when building software we'll find ourselves in a situation where we believe "we need X from other person" before we can start. I've never found this to be 100% true.&lt;br&gt;
I have seen software projects be stuck in a holding pattern where engineers are waiting on each other (this can burn days, or even weeks of time). We can generally always start something.&lt;/p&gt;

&lt;p&gt;For example, maybe you need data from the API before starting the frontend. Stick it in a JSON file and fake the API. You're then unblocked and can get started. You'll then learn things about the data you need and will be able to provide this information to the developer who is working on the API. This will make their job easier and probably get you the API endpoint faster and exactly how you need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Production code is the best code
&lt;/h2&gt;

&lt;p&gt;There's a reason we want to get changes into production as fast as possible.&lt;/p&gt;

&lt;p&gt;When code is successfully merged and deployed to production, we've now eliminated a bunch of uncertainties about it. We know it passes CI, we know it won't bring the site down.&lt;/p&gt;

&lt;p&gt;Even though it's behind a flag, there's always the possibility of something going wrong. Getting it into production increases our trust of it and makes it easier for the team&lt;br&gt;
to build on it moving forward. Confidence is a huge driver of momentum. We need both if we're going to be able to build this feature quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback loop
&lt;/h2&gt;

&lt;p&gt;As this project progresses, we are seeing changes in production daily. Once the feature is somewhat working, we have a good opportunity to start inviting more people into the process. &lt;br&gt;
I like to share with people from security, documentation, support, sales, biz dev etc. Add them to the feature flag and ask them for feedback.  &lt;/p&gt;

&lt;p&gt;Remember how we started with a very basic project plan? At this point we have feedback coming in, we turn that feedback into new issues (tasks on the project board) and it feeds right&lt;br&gt;
back into the development process.&lt;/p&gt;

&lt;p&gt;We are now &lt;strong&gt;ITERATING&lt;/strong&gt; on the feature and making it better. Iterating is easy for the team because we've been making small changes all along. People have a shared context&lt;br&gt;
of how everything works, so contributing is easy. We have confidence because the majority of the code is in production.&lt;/p&gt;

&lt;p&gt;Personally this is my favorite phase of every project. If things were setup correctly from the start, there should be a lot of momentum driving everything forward at this point.&lt;/p&gt;

&lt;p&gt;This process of feedback -&amp;gt; code -&amp;gt; ship continues to loop until we have something we can ship to real users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shipping to real users
&lt;/h2&gt;

&lt;p&gt;Once the team has accomplished the minimal scope, it's time to start getting this new feature out to real users.&lt;br&gt;
The high level process we follow is "Staff ship" -&amp;gt; get feedback -&amp;gt; "General availability". There can be a lot of other details here (documentation, capacity, security, abuse) that depend on the feature.&lt;/p&gt;

&lt;p&gt;The "Staff ship" is when we make the feature available to every employee and ask for feedback. Our company is large enough that this works really well for uncovering &lt;br&gt;
potential problems. During this time we also watch instrumentation more closely for potential errors/performance problems. The ways people use our product is highly&lt;br&gt;
variable and we can't anticipate everything.&lt;/p&gt;

&lt;p&gt;"General availability" is when we make the feature available to everyone. We have tools available to let us roll it out slowly to a % of users. As we do this we continue to&lt;br&gt;
monitor things closely. If we see serious problems we can always turn it off, fix the problem and then continue the roll out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Principles
&lt;/h2&gt;

&lt;p&gt;This was a pretty generalized view of how we work and the details will vary from project to project. But I think I can distill it down to a few important points.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start by defining the MVP. Review and cut scope until it truly feels minimal.&lt;/li&gt;
&lt;li&gt;Software is never done. We are OK with shipping things that aren't perfect. We can always ship another PR to improve it.&lt;/li&gt;
&lt;li&gt;Always be unblocking. Make it easy for people to be contributing at all times (even if alone in a separate timezone).&lt;/li&gt;
&lt;li&gt;The project plan starts minimal and evolves as we ship code. Invite others early to give feedback, incorporate that into the plan as the project progresses.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Some important points
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;you need to be able to deploy and rollback quickly (if you only deploy a couple times a week, this won't work well)&lt;/li&gt;
&lt;li&gt;you need feature flags to gate code and ship only to specific users&lt;/li&gt;
&lt;li&gt;this is a general example of how teams I've been on work (GitHub is a big company and individual teams do what works best for them)&lt;/li&gt;
&lt;li&gt;I'm an engineer, this is an engineering centric view of the process&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>GitHub Actions - Deploy to Heroku</title>
      <dc:creator>Mike Coutermarsh</dc:creator>
      <pubDate>Sat, 02 Nov 2019 18:58:57 +0000</pubDate>
      <link>https://forem.com/mscccc/github-actions-deploy-to-heroku-22np</link>
      <guid>https://forem.com/mscccc/github-actions-deploy-to-heroku-22np</guid>
      <description>&lt;p&gt;Here's how to deploy to Heroku using GitHub Actions. Without adding any new dependencies.&lt;/p&gt;

&lt;p&gt;First, you need a Heroku auth token. You can generate one on your machine using the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;heroku authorizations:create
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Copy the &lt;code&gt;Token&lt;/code&gt; value and add it as a secret to your repository (Go to your repository Settings -&amp;gt; Secrets. Name it &lt;code&gt;HEROKU_API_TOKEN&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;Next, add this to your workflow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Heroku&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;HEROKU_API_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.HEROKU_API_TOKEN }}&lt;/span&gt;
    &lt;span class="na"&gt;HEROKU_APP_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-app-name-here"&lt;/span&gt;
  &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.ref == 'refs/heads/master' &amp;amp;&amp;amp; job.status == 'success'&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git push https://heroku:$HEROKU_API_TOKEN@git.heroku.com/$HEROKU_APP_NAME.git origin/master:master&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will only run for builds on the Master branch and if previous steps have worked properly.&lt;/p&gt;

&lt;p&gt;Here's a full example for a Rails app. This runs your tests, and if successful, deploys to Heroku.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Ruby Test and Deploy&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v1&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Ruby&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-ruby@v1&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;ruby-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2.6.3&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/cache@v1&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vendor/bundle&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ runner.os }}-gem-${{ hashFiles('**/Gemfile.lock') }}&lt;/span&gt;
        &lt;span class="na"&gt;restore-keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;${{ runner.os }}-gem-&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Bundler&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;gem install bundler&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Gems&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bundle install --path vendor/bundle --jobs 4 --retry &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Tests&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;bundle exec rake test&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Heroku&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;HEROKU_API_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.HEROKU_API_TOKEN }}&lt;/span&gt;
        &lt;span class="na"&gt;HEROKU_APP_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-app-name-here"&lt;/span&gt;
      &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.ref == 'refs/heads/master' &amp;amp;&amp;amp; job.status == 'success'&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git push https://heroku:$HEROKU_API_TOKEN@git.heroku.com/$HEROKU_APP_NAME.git origin/master:master&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>githubactions</category>
      <category>heroku</category>
      <category>github</category>
    </item>
    <item>
      <title>Creating images with Ruby + HTML/CSS API</title>
      <dc:creator>Mike Coutermarsh</dc:creator>
      <pubDate>Sun, 10 Mar 2019 21:17:01 +0000</pubDate>
      <link>https://forem.com/mscccc/creating-images-with-ruby--htmlcss-api-16g4</link>
      <guid>https://forem.com/mscccc/creating-images-with-ruby--htmlcss-api-16g4</guid>
      <description>&lt;p&gt;Ever wonder how trendy websites like &lt;a href="https://producthunt.com" rel="noopener noreferrer"&gt;Product Hunt&lt;/a&gt; or &lt;a href="https://medium.com" rel="noopener noreferrer"&gt;Medium&lt;/a&gt; generate those fancy Twitter screenshots?&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1104239882879156224-275" src="https://platform.twitter.com/embed/Tweet.html?id=1104239882879156224"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1104239882879156224-275');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1104239882879156224&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Wonder no more!&lt;/p&gt;

&lt;p&gt;Essentially, they render the HTML/CSS in a headless Chrome instance and take a screenshot. Sound complicated? Yes, it is. Especially "at scale."&lt;/p&gt;

&lt;p&gt;Good thing there are API's for this.&lt;/p&gt;

&lt;p&gt;I will show you how to do this with an API I built specifically for this purpose: &lt;a href="https://htmlcsstoimage.com" rel="noopener noreferrer"&gt;HTML/CSS to Image API&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"httparty"&lt;/span&gt;


&lt;span class="n"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;username: &lt;/span&gt;&lt;span class="s1"&gt;'user_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;password: &lt;/span&gt;&lt;span class="s1"&gt;'api_key'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;div class=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;box&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;&amp;lt;h3&amp;gt;Hello, world 😍&amp;lt;/h3&amp;gt;&amp;lt;/div&amp;gt;"&lt;/span&gt;

&lt;span class="n"&gt;css&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;".box {
  border: 4px solid #8FB3E7;
  padding: 20px;
  color: white;
  font-size: 100px;
  width: 800px;
  height: 400px;
  font-family: 'Roboto';
  background-color: #8BC6EC;
  background-image: linear-gradient(135deg, #8BC6EC 0%, #9599E2 100%);
}"&lt;/span&gt;

&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;HTTParty&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"https://hcti.io/v1/image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="ss"&gt;body: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;html: &lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;css: &lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                      &lt;span class="ss"&gt;basic_auth: &lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# { url: https://hcti.io/v1/image/bfae7d68-86cc-4934-83ac-af3ba75a0d34 }&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhcti.io%2Fv1%2Fimage%2Fbfae7d68-86cc-4934-83ac-af3ba75a0d34" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhcti.io%2Fv1%2Fimage%2Fbfae7d68-86cc-4934-83ac-af3ba75a0d34" alt="Hello, world."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Done. We have an image ✨.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rails + Caching
&lt;/h2&gt;

&lt;p&gt;If you're creating these from Rails and already use memcached, here's a nice trick for ensuring you only create them once.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;cache_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"image/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cache_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="no"&gt;HTTParty&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"https://hcti.io/v1/image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="ss"&gt;body: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;html: &lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;css: &lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                      &lt;span class="ss"&gt;basic_auth: &lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use the html/css to generate the cache key. Don't worry about it being too long. Rails/Dalli automatically hashes the key for you, guaranteeing it will be unique and the correct length.&lt;/p&gt;

&lt;p&gt;This way, if you send the exact same payload again, Rails will pull the URL from cache rather than regenerating it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Another Rails tip
&lt;/h2&gt;

&lt;p&gt;If you're generating these for all of your content, it may be temping to stick the API call into an &lt;code&gt;after_create&lt;/code&gt;. I advise against that. It's always best to keep I/O to an absolute minimum when "in request". Even though the request may only take 30ms, that can add up if the endpoint is already doing a lot.&lt;/p&gt;

&lt;p&gt;The solution, is using a background job.&lt;/p&gt;

&lt;p&gt;So instead of making the call directly in an &lt;code&gt;after_create&lt;/code&gt;. You can instead enqueue the background job using &lt;code&gt;after_create&lt;/code&gt;. Then the image will be generated in the background. Keeping your Rails response times super quick.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build something cool?
&lt;/h2&gt;

&lt;p&gt;If you build something cool this, let me know so I can &lt;a href="https://twitter.com/mscccc" rel="noopener noreferrer"&gt;tweet it!&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>showdev</category>
      <category>api</category>
    </item>
    <item>
      <title>Build a GitHub Action with Ruby</title>
      <dc:creator>Mike Coutermarsh</dc:creator>
      <pubDate>Tue, 15 Jan 2019 16:04:11 +0000</pubDate>
      <link>https://forem.com/mscccc/build-a-github-action-with-ruby-3nln</link>
      <guid>https://forem.com/mscccc/build-a-github-action-with-ruby-3nln</guid>
      <description>&lt;p&gt;Want to build a GitHub Action with everyones favorite language?&lt;/p&gt;

&lt;p&gt;Here's a quick start for building one with Ruby. ✨&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/mscoutermarsh"&gt;
        mscoutermarsh
      &lt;/a&gt; / &lt;a href="https://github.com/mscoutermarsh/ruby-action-recipe"&gt;
        ruby-action-recipe
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Quick start recipe for building an Action with Ruby and the GitHub API.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
This repo is out of date&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;📣 There is now a better way.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Take a look at &lt;a href="https://github.com/actions/setup-ruby"&gt;setup-ruby&lt;/a&gt; for examples on how to use Ruby with Actions.&lt;/p&gt;
&lt;p&gt;❤️&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/mscoutermarsh/ruby-action-recipe"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h2&gt;
  
  
  Fancy gif
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LnBRN-Vn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/http://cloud.mikeasaur.us/fd228f66cf8d/Screen%25252520Recording%252525202019-01-14%25252520at%2525252005.02%25252520PM.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LnBRN-Vn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/http://cloud.mikeasaur.us/fd228f66cf8d/Screen%25252520Recording%252525202019-01-14%25252520at%2525252005.02%25252520PM.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>githunt</category>
      <category>github</category>
      <category>beginners</category>
      <category>ruby</category>
    </item>
    <item>
      <title>High traffic app that can’t take downtime - Data migration</title>
      <dc:creator>Mike Coutermarsh</dc:creator>
      <pubDate>Sun, 13 Jan 2019 23:50:04 +0000</pubDate>
      <link>https://forem.com/mscccc/high-traffic-app-that-cant-take-downtime---data-migration-450d</link>
      <guid>https://forem.com/mscccc/high-traffic-app-that-cant-take-downtime---data-migration-450d</guid>
      <description>&lt;p&gt;When you can't take downtime, the “trick” to data migration is: &lt;strong&gt;Think small changes.&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;New table&lt;/li&gt;
&lt;li&gt;Update writes to go to old and new&lt;/li&gt;
&lt;li&gt;Background job to migrate old data to new&lt;/li&gt;
&lt;li&gt;Move reads to new table &lt;/li&gt;
&lt;li&gt;Stop writing to old table&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each of these steps is a deploy.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Getting started with GitHub Actions? Try Actions Toolkit</title>
      <dc:creator>Mike Coutermarsh</dc:creator>
      <pubDate>Sun, 13 Jan 2019 23:40:51 +0000</pubDate>
      <link>https://forem.com/mscccc/getting-started-with-github-actions-try-actions-toolkit-1902</link>
      <guid>https://forem.com/mscccc/getting-started-with-github-actions-try-actions-toolkit-1902</guid>
      <description>&lt;p&gt;If you're writing your own Actions using Node.js. Save yourself some time and take a look at Actions Toolkit. Jason is collecting common tasks and extracting them to a single module you can use to build your Actions.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/JasonEtco"&gt;
        JasonEtco
      &lt;/a&gt; / &lt;a href="https://github.com/JasonEtco/actions-toolkit"&gt;
        actions-toolkit
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🛠 A toolkit for building GitHub Actions in Node.js
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h3&gt;
GitHub Actions Toolkit&lt;/h3&gt;
&lt;p&gt;
  An opinionated toolkit for building GitHub Actions in Node.js&lt;br&gt;
  &lt;a href="https://raw.githubusercontent.com/JasonEtco/actions-toolkit/main/#usage"&gt;Usage&lt;/a&gt; •
  &lt;a href="https://raw.githubusercontent.com/JasonEtco/actions-toolkit/main/#api"&gt;API&lt;/a&gt; •
  &lt;a href="https://raw.githubusercontent.com/JasonEtco/actions-toolkit/main/#how-to-test-your-github-actions"&gt;How to test your Action&lt;/a&gt; •
  &lt;a href="https://raw.githubusercontent.com/JasonEtco/actions-toolkit/main/#faq"&gt;FAQ&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/JasonEtco/actions-toolkit"&gt;&lt;img alt="GitHub Actions status" src="https://res.cloudinary.com/practicaldev/image/fetch/s--4RRBOeq_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/JasonEtco/actions-toolkit/workflows/Node%2520CI/badge.svg"&gt;&lt;/a&gt; &lt;a href="https://codecov.io/gh/JasonEtco/actions-toolkit/" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/ec329a0372e442de3f3c8017e618543436e7b398/68747470733a2f2f62616467656e2e6e6f772e73682f636f6465636f762f632f6769746875622f4a61736f6e4574636f2f616374696f6e732d746f6f6c6b6974" alt="Codecov"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This toolkit is an opinionated alternative to (and wrapper around) the &lt;a href="https://github.com/actions/toolkit"&gt;official toolkit&lt;/a&gt;. &lt;code&gt;actions/toolkit&lt;/code&gt; makes many features optional in the interest of performance, so you may prefer to use it instead of this library.&lt;/p&gt;

&lt;h2&gt;
Usage&lt;/h2&gt;

&lt;h3&gt;
Installation&lt;/h3&gt;

&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;$ npm install actions-toolkit&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight highlight-source-js"&gt;&lt;pre&gt;&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; Toolkit &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;require&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'actions-toolkit'&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;
&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-s1"&gt;tools&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-k"&gt;new&lt;/span&gt; &lt;span class="pl-v"&gt;Toolkit&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;
Bootstrap a new action&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;$ npx actions-toolkit my-cool-action
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will create a new folder &lt;code&gt;my-cool-action&lt;/code&gt; with the following files:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;├── Dockerfile
├── action.yml
├── index.js
├── index.test.js
└── package.json
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;
API&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/JasonEtco/actions-toolkit/main/#toolkit-options"&gt;The Toolkit class&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/JasonEtco/actions-toolkit/main/#toolsgithub"&gt;Authenticated GitHub API client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/JasonEtco/actions-toolkit/main/#toolslog"&gt;Logging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/JasonEtco/actions-toolkit/main/#toolsinputs"&gt;Getting workflows' inputs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/JasonEtco/actions-toolkit/main/#toolsoutputs"&gt;Output information from your action&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/JasonEtco/actions-toolkit/main/#toolscommandcommand-args-match--promise"&gt;Slash commands&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/JasonEtco/actions-toolkit/main/#toolsreadfilepath-encoding--utf8"&gt;Reading files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/JasonEtco/actions-toolkit/main/#toolsexec"&gt;Run a CLI command&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/JasonEtco/actions-toolkit/main/#toolsexit"&gt;End the action's process&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/JasonEtco/actions-toolkit/main/#toolscontext"&gt;Inspect the webhook event payload&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
Toolkit options&lt;/h3&gt;
&lt;h4&gt;
event (optional)&lt;/h4&gt;
&lt;p&gt;An optional list…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/JasonEtco/actions-toolkit"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>githunt</category>
    </item>
    <item>
      <title>Refactoring Tip: Use the View Object pattern in Rails for building a user profile page</title>
      <dc:creator>Mike Coutermarsh</dc:creator>
      <pubDate>Sun, 14 May 2017 17:47:32 +0000</pubDate>
      <link>https://forem.com/mscccc/using-the-view-object-pattern-in-rails-for-modeling-mediums-user-profile-page</link>
      <guid>https://forem.com/mscccc/using-the-view-object-pattern-in-rails-for-modeling-mediums-user-profile-page</guid>
      <description>&lt;p&gt;Medium.com’s user profile shows all of the users &lt;strong&gt;posts&lt;/strong&gt;, their &lt;strong&gt;followers&lt;/strong&gt; and what they have &lt;strong&gt;highlighted&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fecp5079h5hche6bm2of4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fecp5079h5hche6bm2of4.png" alt="mediums profile page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’d imagine their data model works like this. They have a &lt;strong&gt;User&lt;/strong&gt; model, a &lt;strong&gt;Post&lt;/strong&gt; model, a &lt;strong&gt;FollowerAssociationModel&lt;/strong&gt; and a &lt;strong&gt;Highlights&lt;/strong&gt; model.&lt;/p&gt;

&lt;p&gt;For their profile page, they bring in data from several different sources.&lt;/p&gt;

&lt;p&gt;When building out a users profile page in your app, it might feel tempting to create an entirely new model for it. But I'm generally very wary of creating a model for something so non-specific. It can quickly become a general "throw everything here" model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use the View Object Pattern
&lt;/h2&gt;

&lt;p&gt;The best way I have found to do this in Rails is to use the View Object Pattern (aka Presenter Object). You can read more about it here: &lt;a href="http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/" rel="noopener noreferrer"&gt;7 Patterns to Refactor Fat ActiveRecord Models&lt;/a&gt; (search view object).&lt;/p&gt;

&lt;p&gt;First, you'd create a class that encapsulates all the data you want shown on the profile page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Something like this:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserProfile&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tagline&lt;/span&gt;
    &lt;span class="c1"&gt;# example of some html conversion&lt;/span&gt;
    &lt;span class="vi"&gt;@tagline&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;ConvertTagsToLinks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tagline&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;posts&lt;/span&gt;
    &lt;span class="vi"&gt;@posts&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;order_by_featured_date&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;followers&lt;/span&gt;
    &lt;span class="vi"&gt;@follows&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;followers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ordered_by_popularity&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;## ect...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(a bit of a contrived example, but hopefully you get the idea)&lt;/p&gt;

&lt;p&gt;Then this makes it really easy to have one nice clean object to access in your controllers and views.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# some controller&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
  &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="vi"&gt;@user_profile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# render a view...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in your view, you are able to easily access your view object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;p class="tagline"&amp;gt;&amp;lt;%= @user_profile.tagline %&amp;gt;&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using this pattern keeps your abstractions very explicit. This pattern is easy to write tests for and helps keep User Profile code out of your models.&lt;/p&gt;

&lt;p&gt;Give it a try and let me know how it works out for you.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>model</category>
      <category>refactor</category>
    </item>
    <item>
      <title>My Top 3 Ruby on Rails Best Practices</title>
      <dc:creator>Mike Coutermarsh</dc:creator>
      <pubDate>Wed, 29 Mar 2017 21:10:11 +0000</pubDate>
      <link>https://forem.com/mscccc/top-3-ruby-on-rails-best-practices</link>
      <guid>https://forem.com/mscccc/top-3-ruby-on-rails-best-practices</guid>
      <description>&lt;p&gt;Here is what will give you the biggest bang for your effort.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Learn the &lt;strong&gt;presenter&lt;/strong&gt; and &lt;strong&gt;service object&lt;/strong&gt; patterns. This allows you to break down complex logic into small, self contained and easily tested classes. This makes writing/changing/reading code easy. Remember to namespace things and create clear separation between different objects. Learn more here: &lt;a href="http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/"&gt;7 Patterns to Refactor Fat ActiveRecord Models&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Roughly follow Sandi Metz rules: &lt;a href="https://robots.thoughtbot.com/sandi-metz-rules-for-developers"&gt;Sandi Metz' Rules For Developers&lt;/a&gt;. No need to follow them exactly. But use them as a guideline. Small models/short methods. Methods should do 1 thing only. You can use something like Rubocop to force yourself/the whole team to follow these rules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don't be too clever. What I mean by this is: &lt;strong&gt;Keep it simple and follow patterns&lt;/strong&gt;. Don't add complexity prematurely. You may think you need that fancy event handler/rabbitmq/etc Ruby gem - but it can probably wait. I like to follow the rule of “do I have 3 problems I can solve with this?” before I add in something non-standard (I think I stole this idea from Sandi Metz' book: &lt;a href="http://www.poodr.com/"&gt;POODR&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I hope this helps!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>tips</category>
    </item>
    <item>
      <title>Hi, I'm Mike Coutermarsh</title>
      <dc:creator>Mike Coutermarsh</dc:creator>
      <pubDate>Wed, 28 Sep 2016 22:22:45 +0000</pubDate>
      <link>https://forem.com/mscccc/hi-im-mike-coutermarsh</link>
      <guid>https://forem.com/mscccc/hi-im-mike-coutermarsh</guid>
      <description>&lt;p&gt;I have been coding for [number] years.&lt;/p&gt;

&lt;p&gt;You can find me on Twitter as &lt;a href="https://twitter.com/mscccc" rel="noopener noreferrer"&gt;@mscccc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I live in [city].&lt;/p&gt;

&lt;p&gt;I work for [company]&lt;/p&gt;

&lt;p&gt;I mostly program in these languages: [languages].&lt;/p&gt;

&lt;p&gt;I am currently learning more about [topic].&lt;/p&gt;

&lt;p&gt;Nice to meet you.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
