<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Jeremy Dye fyi</title>
    <description>I make stuff on the internet sometimes</description>
    <link>https://jeremydyefyi.com/</link>
    <atom:link href="https://jeremydyefyi.com/feed.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>AWS Elastic Beanstalk Slack Notifications</title>
        <description>&lt;p&gt;If you’re like me, you use Elastic Beanstalk because it provides a nice Heroku like experience for deploying apps while still having all the flexibility of being on AWS. If you’re even more like me, you like using Slack as a hub for software engineering operations. This is a quick guide to integrate the two.&lt;/p&gt;

&lt;h2 id=&quot;the-journey&quot;&gt;The Journey&lt;/h2&gt;
&lt;p&gt;I google’d “elastic beanstalk slack notifications” and didn’t find anything super simple to just get these darn notifications into Slack. I found a paid app that’s $5/mo per user and said “Pshhh nah, that’s almost how much I pay for my actual Slack licenses”. I found some AWS articles that talk about the built in notification SNS topic Beanstalk comes with (which is awesome), but not how to pipe it into Slack. I setup AWS Chat Bot, only to figure out &lt;a href=&quot;https://docs.aws.amazon.com/chatbot/latest/adminguide/related-services.html&quot;&gt;it doesn’t support Beanstalk&lt;/a&gt;. Eventually, I came across a Lambda for sending Slack messages via Webhook. That’ll do bot, that’ll do.&lt;/p&gt;

&lt;h2 id=&quot;the-guide&quot;&gt;The Guide&lt;/h2&gt;

&lt;p&gt;This is what I ended up doing. It’s probably not the best approach, but it gets the job done.&lt;/p&gt;

&lt;h3 id=&quot;slack-webhook&quot;&gt;Slack Webhook&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Open up the Slack workspace you want to integrate with and go to Tools &amp;gt; Workflow Builder.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;This’ll open up the Workflow Builder window. From there click the green “Create” button. Come up with a name and click “Next”.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Now you’ll be prompted how the workflow gets started, select “Webhook”.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;On the next screen, click “Add variable”. Set the key to “message” and the data type should be text. Click “Done” to save the variable and then click the green “Next” button.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Now you’ll be presented with a visualization of the workflow. Click “Add step” and add the “Send a message” step. Select the channel you want to send to. Click “Insert a variable”, select “message”, and click the green “Save” button.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Next click the green “Publish” button in the top right. You’ll get some lovely confetti and your webhook URL. Copy that URL.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;aws-lambda&quot;&gt;AWS Lambda&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Open the AWS console, make sure you’re in the right region for your Beanstalk, and go to AWS Lambda.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Click the orange “Create function” button. Leave it on the “Author from scratch” option, give the function a name, and select the Python runtime. You can leave everything else alone and click “Create function”.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Once the function is created, click “Add trigger”. Then pick “SNS” as your source. Next pick the Beanstalk topic you want, they’ll all start with “ElasticBeanstalkNotifications”. Now click “Add”.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Click the “Code” tab and paste in the code below.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Finally, click “Deploy” and enjoy those sweet, sweet Slack notifications.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;urllib3&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;json&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urllib3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PoolManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;lambda_handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;WEBHOOK URL GOES HERE&quot;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Records'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Sns'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Message'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;encoded_msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'utf-8'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;resp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'POST'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoded_msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;NOTE:&lt;/em&gt; I split the string because there’s a lot of boilerplate in the messages. If you want everything, you can remove that and pass in the whole message.&lt;/p&gt;
</description>
        <pubDate>Sat, 08 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://jeremydyefyi.com/2022/10/08/aws-elastic-beanstalk-slack-notifications/</link>
        <guid isPermaLink="true">https://jeremydyefyi.com/2022/10/08/aws-elastic-beanstalk-slack-notifications/</guid>
      </item>
    
      <item>
        <title>Adding a Custom Generator to Rails Scaffold</title>
        <description>&lt;p&gt;This took me wayyy too long to figure out, so I figured I’d share an end to end guide. Shoutout to this &lt;a href=&quot;https://gist.github.com/annikoff/331f785aa7a207a7945b1eca6eff526b&quot;&gt;GitHub gist&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;

&lt;p&gt;If you’re like me, you hate typing boilerplate so you use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rails g scaffold Thing&lt;/code&gt;. Oftentimes, we come up with design patterns that aren’t covered by the Rails default scaffold. To get around this, you can create custom generators.&lt;/p&gt;

&lt;h2 id=&quot;create-a-generator&quot;&gt;Create a Generator&lt;/h2&gt;

&lt;p&gt;First, we’ll create our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Something&lt;/code&gt; generator. Note that this is namespaced under the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rails&lt;/code&gt; module.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rails g generator rails/something
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now that you’ve generated it, fill out the resulting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USAGE&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;something_generator.rb&lt;/code&gt; files like so.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Description:
    Generates something

Example:
    bin/rails generate something Thing

    This will create:
      app/something/thing.rb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Rails::SomethingGenerator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Generators&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;NamedBase&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;source_root&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;expand_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;templates&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__dir__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_something&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;file_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;app/something/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.rb&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;create_file&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;# Oh hai there&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you want to be extra fancy, you can create a template and spec! But I don’t feel like it so here we go.&lt;/p&gt;

&lt;h2 id=&quot;initializer&quot;&gt;Initializer&lt;/h2&gt;

&lt;p&gt;Next we need to create an initializer to hook into the scaffold generator. I called mine &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config/initializers/custom_scaffold_generators.rb&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;rails/railtie&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;rails/generators&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;rails/generators/rails/scaffold_controller/scaffold_controller_generator&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;SomethingGenerator&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ScaffoldControllerGenerator&lt;/span&gt;
    &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveSupport&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Concern&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;included&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;hook_for&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;in: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;default: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;type: :boolean&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ActiveModel&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Railtie&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Railtie&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;generators&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Generators&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;configure!&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;generators&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Generators&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ScaffoldControllerGenerator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SomethingGenerator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ScaffoldControllerGenerator&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that we set it so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default: true&lt;/code&gt;, so it’s automatically included in the scaffold. Voila, you’ve got a working custom scaffold generator.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rails g scaffold Thing
      invoke  active_record
      create    db/migrate/20220618203059_create_things.rb
      create    app/models/thing.rb
      ... a bunch of stuff we don't care about in this post
      invoke    something
      create      app/something/thing.rb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sat, 18 Jun 2022 00:00:00 +0000</pubDate>
        <link>https://jeremydyefyi.com/2022/06/18/adding-a-custom-generator-to-rails-scaffold/</link>
        <guid isPermaLink="true">https://jeremydyefyi.com/2022/06/18/adding-a-custom-generator-to-rails-scaffold/</guid>
      </item>
    
      <item>
        <title>Thoughts on Hiring</title>
        <description>&lt;p&gt;I recently &lt;a href=&quot;https://jeremydye.fyi/2022/04/09/why-i-decided-to-start-a-startup/&quot;&gt;started a startup&lt;/a&gt;. I have experience with hiring. I’ve refined job descriptions, designed technical interviews, discussed DEI tactics, interviewed hundreds of candidates, and done many other activities. One thing I had not done prior to my startup: implement an entire hiring process from scratch.&lt;/p&gt;

&lt;p&gt;We started WaySync on March 28th and my #1 priority from the first day was hiring our founding team of engineers. By May 13th, we had signed 3 candidates. Here’s some thoughts after going through this experience.&lt;/p&gt;

&lt;h2 id=&quot;know-what-youre-looking-for&quot;&gt;Know what you’re looking for.&lt;/h2&gt;

&lt;p&gt;Invest time into writing a good job description. Clearly communicate what your company is trying to accomplish, the skills + qualities successful candidates should have, and what you offer candidates. Do it in a voice that is authentic to you instead of copying a generic, sterile template. The extra effort you spend here will pay dividends by aligning your team, delivering higher intent applicants, and providing a framework for the rest of your hiring process.&lt;/p&gt;

&lt;p&gt;This last point is crucial. How can you effectively interview candidates without understanding what they need to accomplish and the skills necessary to do so? Use your job description as a blueprint for what your interviews should be evaluating. Design your interviews to produce clear signals on whether the candidates have the skills + qualities you decided on. Need someone who can deliver features with minimal guidance? Give them a vague use story and let them build. Do you need someone who can optimize your application’s performance? Give them an architecture + data and see what they come up with.&lt;/p&gt;

&lt;h2 id=&quot;always-be-selling&quot;&gt;Always be selling.&lt;/h2&gt;

&lt;p&gt;I truly believe that interviewing is a two way street. Great candidates have a lot of options, so make sure you’re selling them on working with you. I highly recommend reflecting on what you have to offer and even including it explicitly in the job description. Do you offer top compensation, a noble mission, specific technologies, growth opportunities, etc? Tell candidates!&lt;/p&gt;

&lt;p&gt;A great job description / outreach copy will get the conversation started, but you should also look at every other step in the process as opporunity to woo candidates. Do interviews with a friendly demeanor, give the candidate time to ask questions each session (make yourself available to answer additional questions), and pay attention to their questions to understand what their concerns are so you can directly address them. Above all else, treat candidates with kindness and respect. The goal is that even if they don’t receive an offer, they leave the process with a positive impression of the company.&lt;/p&gt;

&lt;h2 id=&quot;create-an-effective-initial-screening-process&quot;&gt;Create an effective initial screening process.&lt;/h2&gt;

&lt;p&gt;One mistake I made was not having an effective screening call. 90% of candidates went on to additional (more costly) rounds. I don’t have any concrete advice here. I recently read the book &lt;a href=&quot;https://whothebook.com/&quot;&gt;Who&lt;/a&gt;. I really wish I had read it &lt;em&gt;before&lt;/em&gt; I started hiring, I plan to utilize their top of funnel strategies next time.&lt;/p&gt;

&lt;h2 id=&quot;invest-in-your-network&quot;&gt;Invest in your network.&lt;/h2&gt;

&lt;p&gt;I was fortunate enough to be able to recruit a former colleague. Working with someone day to day is pretty much the best signal you’re going to get when it comes to hiring. It can be really comforting to have a known quantity come in, especially with brand new teams. Make sure to consider how the role compares to the one you knew them in. For example, someone successful at a FAANG company won’t necessarily succeed at an early stage startup. Take a stroll through your LinkedIn connections and catch up with the talented folks you know, it’s worth it.&lt;/p&gt;

&lt;h2 id=&quot;there-are-no-shortcuts&quot;&gt;There are no shortcuts.&lt;/h2&gt;

&lt;p&gt;Put in the work. Reach out to a &lt;em&gt;lot&lt;/em&gt; of candidates. Aggressively pursue new recruiting channels and strategies. You can do this.&lt;/p&gt;
</description>
        <pubDate>Tue, 31 May 2022 00:00:00 +0000</pubDate>
        <link>https://jeremydyefyi.com/2022/05/31/thoughts-on-hiring/</link>
        <guid isPermaLink="true">https://jeremydyefyi.com/2022/05/31/thoughts-on-hiring/</guid>
      </item>
    
      <item>
        <title>Why I Decided to Start a Startup</title>
        <description>&lt;p&gt;Why I decided to start a startup.&lt;/p&gt;

&lt;p&gt;Why I decided to found a firm.&lt;/p&gt;

&lt;p&gt;Why I decided to commence a conglomerate.&lt;/p&gt;

&lt;p&gt;Why I decided to create a corporation.&lt;/p&gt;

&lt;p&gt;Why I decided to begin a business.&lt;/p&gt;

&lt;p&gt;Why I decided to launch a venture.&lt;/p&gt;

&lt;p&gt;Why I decided to do a startup.&lt;/p&gt;

&lt;p&gt;Why I decided to produce an organization.&lt;/p&gt;

&lt;p&gt;Why I decided to setup an outfit.&lt;/p&gt;

&lt;p&gt;Why I decided to generate an enterprise.&lt;/p&gt;

&lt;p&gt;Why I decided to undertake a establishment.&lt;/p&gt;

&lt;p&gt;Why I decided to make a firm.&lt;/p&gt;

&lt;p&gt;Why I decided to instigate a venture.&lt;/p&gt;

&lt;p&gt;Why I decided to originate a organization.&lt;/p&gt;

&lt;p&gt;Why I decided to bring about a business.&lt;/p&gt;

&lt;p&gt;Why I decided to embark on a journey.&lt;/p&gt;

&lt;p&gt;Sorry, “start a startup” is such a funny phrase to me. I can’t help but think of all the different ways to phrase it. Anyways, I recently did this. I wanted to write down my thought process.&lt;/p&gt;

&lt;h1 id=&quot;what-do-i-want&quot;&gt;What do I want?&lt;/h1&gt;

&lt;h2 id=&quot;ownership&quot;&gt;Ownership&lt;/h2&gt;
&lt;p&gt;I want the opportunity to die by my own sword. I’ve worked at startups my whole career. I’ve even had the privilege of leading teams with a high degree of autonomy at some of them. When I reflect on my career, the most frustrating parts were when I disagreed with the company’s direction. I want the buck to stop with me this time.&lt;/p&gt;

&lt;h2 id=&quot;fun&quot;&gt;Fun&lt;/h2&gt;
&lt;p&gt;I want my day to day to be fun. I love the energy of small teams where ideas are flowing, memes are flourishing, and people are able to play off one another like a jazz band. On top of that, I find myself energized by all the minutiae you’re presented with as a founder (what’s our culture, what health plans do we offer, should we get an office, etc).&lt;/p&gt;

&lt;h2 id=&quot;compensation&quot;&gt;Compensation&lt;/h2&gt;
&lt;p&gt;I want to be well compensated. At a glance, this seems at odds with starting a startup. This isn’t my first rodeo though. After a decade of working at startups, I know I have the skills to win. I think you probably shouldn’t start one unless you have deep conviction you’re capable of winning. It will carry you through the moments of doubt.&lt;/p&gt;

&lt;h1 id=&quot;other-considerations&quot;&gt;Other considerations&lt;/h1&gt;

&lt;h2 id=&quot;timing&quot;&gt;Timing&lt;/h2&gt;
&lt;p&gt;I’m 31. I’m not getting any younger. I might have children in the near future. My window of being able to pour everything I’ve got into something seems like it’s closing. I felt the right opportunity came my way and that I should take it.&lt;/p&gt;

&lt;h2 id=&quot;opportunity-cost&quot;&gt;Opportunity cost&lt;/h2&gt;
&lt;p&gt;I could go work at a large tech company and make a bunch of money, but I’d be lacking in the ownership and fun departments again. I figure if this doesn’t work out, they’ll still be around after.&lt;/p&gt;

&lt;h1 id=&quot;summary&quot;&gt;Summary&lt;/h1&gt;

&lt;p&gt;To be honest, this was a decision I struggled with. I was coming off &lt;a href=&quot;https://techcrunch.com/2021/12/01/better-com-lays-off-9-of-its-staff/&quot;&gt;really&lt;/a&gt; &lt;a href=&quot;https://techcrunch.com/2022/04/03/better-com-teaches-us-how-not-to-conduct-mass-layoffs/&quot;&gt;weird&lt;/a&gt; &lt;a href=&quot;https://techcrunch.com/2022/04/08/better-com-cto-steps-down-agrees-to-voluntary-separation-in-wake-of-mass-layoffs/&quot;&gt;time&lt;/a&gt; at Better (a story for another day perhaps). I had a lot of interesting opportunities available. I was stuck in analysis paralysis trying to decide what to do. I asked a friend for advice. They told me to think about what I might regret not doing. After that, everything became clear.&lt;/p&gt;
</description>
        <pubDate>Sat, 09 Apr 2022 00:00:00 +0000</pubDate>
        <link>https://jeremydyefyi.com/2022/04/09/why-i-decided-to-start-a-startup/</link>
        <guid isPermaLink="true">https://jeremydyefyi.com/2022/04/09/why-i-decided-to-start-a-startup/</guid>
      </item>
    
      <item>
        <title>Rails 7 and React Install Guide</title>
        <description>&lt;p&gt;I love Rails! I also really like React for complex, interactive components. I’ve found it very product to use Turbo and Stimulus (from &lt;a href=&quot;https://hotwired.dev/&quot;&gt;Hotwire&lt;/a&gt;) with sprinkles of React.&lt;/p&gt;

&lt;p&gt;With Rails 7, esbuild is now the default javascript tooling. In the past, I’ve used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;react-rails&lt;/code&gt; but their documentation is still aimed at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;webpacker&lt;/code&gt; based Rails projects. Thankfully, &lt;a href=&quot;https://github.com/reactjs/react-rails/issues/1149#issuecomment-1003318505&quot;&gt;a kind soul&lt;/a&gt; found a working setup with esbuild. I took their working example repo and made this step by step guide.&lt;/p&gt;

&lt;h3 id=&quot;dependencies&quot;&gt;Dependencies&lt;/h3&gt;
&lt;p&gt;Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gem &quot;react-rails&quot;&lt;/code&gt; to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gemfile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add the following to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;esbuild-plugin-import-glob&quot;: &quot;^0.1.1&quot;,
&quot;react&quot;: &quot;^17.0.2&quot;,
&quot;react-dom&quot;: &quot;^17.0.2&quot;,
&quot;react_ujs&quot;: &quot;^2.6.1&quot;,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Install these using your preferred command line tools.&lt;/p&gt;

&lt;h3 id=&quot;esbuild&quot;&gt;esbuild&lt;/h3&gt;
&lt;p&gt;Add the following to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;esbuild.config.js&lt;/code&gt;. Below the existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;require&lt;/code&gt; statements at the top of the file:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const ImportGlobPlugin = require('esbuild-plugin-import-glob').default;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ImportGlobPlugin()&lt;/code&gt; to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugins&lt;/code&gt; array in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config&lt;/code&gt; object. It should look like this after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugins: [rails(), ImportGlobPlugin()],&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loader: { '.js': 'jsx' },&lt;/code&gt; to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config&lt;/code&gt; object.&lt;/p&gt;

&lt;h3 id=&quot;components&quot;&gt;Components&lt;/h3&gt;
&lt;p&gt;Create the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/javascript/components&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/javascript/components/index.js&lt;/code&gt; file with the following contents:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;./**/*.jsx&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;componentsContext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;componentsContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.jsx&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/--/g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ReactRailsUJS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react_ujs&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;ReactRailsUJS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getConstructor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;componentsContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;ReactRailsUJS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handleEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;turbo:load&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ReactRailsUJS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handleMount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;ReactRailsUJS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handleEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;turbo:frame-load&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ReactRailsUJS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handleMount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;ReactRailsUJS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handleEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;turbo:before-render&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ReactRailsUJS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handleUnmount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;import &quot;./components&quot;&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;application.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Create a component to render. Here’s a simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HelloWorld.jsx&lt;/code&gt; component you can use:&lt;/p&gt;

&lt;div class=&quot;language-jsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HelloWorld&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Hello World&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Voila, you can use your component.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;react_component&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;HelloWorld&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Sat, 15 Jan 2022 00:00:00 +0000</pubDate>
        <link>https://jeremydyefyi.com/2022/01/15/rails-7-and-react-install-guide/</link>
        <guid isPermaLink="true">https://jeremydyefyi.com/2022/01/15/rails-7-and-react-install-guide/</guid>
      </item>
    
      <item>
        <title>Company Values</title>
        <description>&lt;p&gt;I’ve been thinking about starting a company. Lately, I’ve found myself often having conversations where I explain the values I’d like my company to have. I’m going to write them down here, both to save myself the repetitions and to refine them.&lt;/p&gt;

&lt;h3 id=&quot;work-smarter-not-harder&quot;&gt;Work Smarter, Not Harder&lt;/h3&gt;
&lt;p&gt;We set audacious goals. We count on and encourage your ingenuity so that we can reach them. We don’t reward people based on hours worked, and we don’t police when, where, or how you work. We reward people based on accomplishing the goals.&lt;/p&gt;

&lt;h3 id=&quot;speak-up&quot;&gt;Speak Up&lt;/h3&gt;
&lt;p&gt;We hire talented people because we truly believe that the right idea, at the right time can be transformational. We make space to hear out our colleagues so that we can capture that. We provide feedback early and often to one another because small frictions can build up and ruin relationships.&lt;/p&gt;

&lt;h3 id=&quot;progress-over-perfection&quot;&gt;Progress Over Perfection&lt;/h3&gt;
&lt;p&gt;We value forward progress over meticulous planning because we believe a rapid, iterative cycle of shipping, gathering feedback + data, and refining is how great products are built. We know everything we do has tradeoffs, so we are aggressive about identifying and collecting the right data to make informed decisions quickly.&lt;/p&gt;

&lt;h3 id=&quot;do-the-right-thing&quot;&gt;Do the Right Thing&lt;/h3&gt;
&lt;p&gt;We strive to do right by our colleagues, customers, and the world around us even if it means less optimal business outcomes. We are tired of companies that profit off of negative externalities and know we can do better.&lt;/p&gt;
</description>
        <pubDate>Fri, 14 Jan 2022 00:00:00 +0000</pubDate>
        <link>https://jeremydyefyi.com/2022/01/14/company-values/</link>
        <guid isPermaLink="true">https://jeremydyefyi.com/2022/01/14/company-values/</guid>
      </item>
    
      <item>
        <title>“Finding” Your Way to Better Security in Multitenant Rails Applications</title>
        <description>&lt;p&gt;Let’s say you’ve created a SaaS application that lets customers keep track of their vendors. Things are going well and you’re adding many customers. One day, a curious customer starts messing around with the IDs in URLs and stumbles across a vendor they shouldn’t have access to. This is Very Bad™, especially if your customers are relying on your application to store sensitive information!&lt;/p&gt;

&lt;p&gt;You have now entered the wide world of Authorizations. We’ll spend this blog post looking at one piece of the Authorization puzzle: using the Finder pattern to ensure users only see the things they’re allowed to.&lt;/p&gt;

&lt;h2 id=&quot;the-problem-illustrated&quot;&gt;The problem, illustrated&lt;/h2&gt;
&lt;p&gt;Let’s say you’re building the application we alluded to in the previous paragraph. One may begin with a naive implementation such as:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VendorsController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@vendors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Vendor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;all&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@vendor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Vendor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This may work fine and dandy at first, but as soon as you add your second customer you’re going to have a problem: every user has access to every vendor. Let’s say you foresee this problem. You create a User model that users authenticate with, add a user_id column to Vendors, and update your controller like so:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VendorsController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@vendors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Vendor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;user_id: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@vendor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Vendor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;user_id: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Great! You also remembered to add scoping to your show route. A+, problem solved, ship it. All is well, for a time…&lt;/p&gt;

&lt;p&gt;A month later you’ve moved on to other features in the application. A new engineer on the team is tasked with adding an Agreement model to keep track of the obligations between customers and each customer’s vendors. She implements the route for creating a new Agreement like so:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AgreementsController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@agreement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Agreement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@vendors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Vendor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;all&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The team is busy, as startups are, and the change slips through to production. The support tickets start streaming in with customers asking about strange vendors showing up. No bueno. What’s an engineer to do?&lt;/p&gt;

&lt;h2 id=&quot;example-usage&quot;&gt;Example usage&lt;/h2&gt;
&lt;p&gt;The Finder pattern is a simple concept: when you want to show something to a user, use a Finder. Finders implement a base scope upon initialization so that users only see what they’re allowed to. Subsequent methods chain off of that main scope, to ensure only a subset of the authorized scope is returned.&lt;/p&gt;

&lt;p&gt;Let’s take a look at what a simple finder might look like for Vendors:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VendorFinder&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;attr_reader&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:scope&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@scope&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Vendor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;user_id: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;by_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@scope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And how it might be used in our controllers:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VendorsController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@vendors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;VendorFinder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;scope&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@vendor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;VendorFinder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;by_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AgreementsController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@agreement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Agreement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@vendors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;VendorFinder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;scope&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finders are most frequently used in controllers, but they can - and should - be used everywhere you are scoping to an authorized subset of records. Part of the security benefit is that when it is used everywhere as a convention, engineers are less likely to customize their own scoping and make an error.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;While this was a simple implementation, it illustrated a few key benefits. The Finder pattern:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Provides a safe, consistent pattern for you to show things to the user;&lt;/li&gt;
  &lt;li&gt;Requires the information it needs to provide that safety during initialization;&lt;/li&gt;
  &lt;li&gt;Centralizes the logic of who should see what; and,&lt;/li&gt;
  &lt;li&gt;Is easy to test.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some might say that in lieu of the Finder pattern, authorization problems could be mitigated with better code review, documentation, or in our specific case, using a /users/:id/vendors route. But, without the Finder pattern, engineers will always need to be thinking through the complexities of each individual scenario: “What vendors can this customer see?” or “Is this User an admin that can see all Agreements?”, etc. With the Finder pattern, you can instead use the simple heuristic of “Will the user see this?” when writing or reviewing code.&lt;/p&gt;

&lt;p&gt;The important concepts here are that applications grow complex, models can be accessed from a variety of contexts, expertise in a system is spread unevenly across a team, and humans just make mistakes sometimes. It’s up to us as engineers to put in guardrails and conventions to prevent these mistakes when we can, and the Finder pattern is yet another tool at our disposal.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post was originally published on the &lt;a href=&quot;https://www.aptible.com/blog/finder-pattern-security-multitenant-rails&quot;&gt;Aptible blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Wed, 29 Jul 2020 00:00:00 +0000</pubDate>
        <link>https://jeremydyefyi.com/2020/07/29/finder-pattern/</link>
        <guid isPermaLink="true">https://jeremydyefyi.com/2020/07/29/finder-pattern/</guid>
      </item>
    
  </channel>
</rss>
