<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Stuff I Learned]]></title><description><![CDATA[I'm a full stack developer, musician, and educator living in Minneapolis.]]></description><link>https://blog.kellenbaker.com</link><generator>RSS for Node</generator><lastBuildDate>Mon, 12 Oct 2026 18:59:27 GMT</lastBuildDate><atom:link href="https://blog.kellenbaker.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How To Run Personal and Work Claude Code Accounts Side-by-Side]]></title><description><![CDATA[Say you have two Claude accounts: a personal one you pay for, and a work one your company pays for. The work account should only ever touch company repos. The personal one is for everything else.
By d]]></description><link>https://blog.kellenbaker.com/how-to-run-personal-and-work-claude-code-accounts-side-by-side</link><guid isPermaLink="true">https://blog.kellenbaker.com/how-to-run-personal-and-work-claude-code-accounts-side-by-side</guid><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Wed, 26 Aug 2026 15:57:26 GMT</pubDate><content:encoded><![CDATA[<p>Say you have two Claude accounts: a personal one you pay for, and a work one your company pays for. The work account should only ever touch company repos. The personal one is for everything else.</p>
<p>By default, Claude Code doesn't know the difference. Everything lives in <code>~/.claude</code>, and switching accounts means logging out and back in — which means losing whatever session you were in the middle of. That's annoying enough in a terminal. It's worse when you're also using Claude Code through an IDE's agent panel and can't just pop open a second tab.</p>
<p>Here's how I set mine up to run both, fully isolated, so I never have to run <code>/status</code> to check which account I'm on ever again.</p>
<h2>The fix: <code>CLAUDE_CONFIG_DIR</code></h2>
<p>Claude Code reads an environment variable called <code>CLAUDE_CONFIG_DIR</code> at startup. Point it at a folder, and that's where Claude Code stores its credentials, session history, and settings — instead of the default <code>~/.claude</code>.</p>
<p>Give each account its own folder, and you get two fully independent Claude Code identities that never touch each other's data.</p>
<p>This used to be an undocumented trick — for a long time the only reference was a <a href="https://github.com/anthropics/claude-code/issues/33430">GitHub issue</a> asking Anthropic to document it, with people using it anyway because it clearly worked. It's since graduated to <a href="https://code.claude.com/docs/en/env-vars#variables">officially documented status</a>, multi-account use case and all.</p>
<h2>Terminal setup</h2>
<h3>1. Create a config folder for each account</h3>
<pre><code class="language-bash">mkdir -p ~/.claude-personal
mkdir -p ~/.claude-work
</code></pre>
<h3>2. Add shell functions</h3>
<p>Drop these in your <code>~/.zshrc</code> (or <code>~/.bashrc</code>):</p>
<pre><code class="language-bash">claude-personal() {
    CLAUDE_CONFIG_DIR=~/.claude-personal claude "$@"
}

claude-work() {
    CLAUDE_CONFIG_DIR=~/.claude-work claude "$@"
}
</code></pre>
<p>Reload your shell:</p>
<pre><code class="language-bash">source ~/.zshrc
</code></pre>
<h3>3. Log in to each one, once</h3>
<pre><code class="language-bash">claude-personal /login
claude-work /login
</code></pre>
<p>Each stores its credentials in its own folder. From here on, <code>claude-personal</code> and <code>claude-work</code> are two totally separate Claude Code instances — separate auth, separate conversation history, separate everything. You can even run them at the same time in separate terminals.</p>
<h3>4. Don't share history between them</h3>
<p>You'll find posts out there suggesting you symlink the two <code>projects</code> folders together so both accounts can <code>--resume</code> each other's sessions. I'd skip that. If your work account is only supposed to touch company repos, merging its session history with your personal one means company code and conversations end up sitting in the same directory tree as your personal projects — which is exactly the kind of thing that ends up in a dotfiles backup or a personal cloud sync without you noticing. Keep them separate.</p>
<h2>Automatically summon the correct Claude</h2>
<p>Nothing stops you from typing <code>claude</code> (personal) while sitting inside a work repo. It's just two commands; remembering which one to use is on you.</p>
<p>I never want to run my personal Claude in a work directory; I never want to run my work Claude in a personal directory. <a href="https://direnv.net/"><code>direnv</code></a> solves this by setting the variable automatically based on which directory you're in:</p>
<pre><code class="language-bash"># .envrc in the root of a company repo
export CLAUDE_CONFIG_DIR=~/.claude-work
</code></pre>
<pre><code class="language-bash">direnv allow
</code></pre>
<p>Now <code>cd</code>-ing into that repo sets <code>CLAUDE_CONFIG_DIR</code> for you — plain <code>claude</code> just does the right thing. Keep <code>.envrc</code> out of the repo's history with a local, unshared ignore rule (don't touch the project's actual <code>.gitignore</code> — this is your workflow, not the team's):</p>
<pre><code class="language-bash">echo '.envrc' &gt;&gt; .git/info/exclude
</code></pre>
<h2>Doing the same thing in Zed's Agent Panel</h2>
<p>If you're only using Claude Code from the terminal, you're done. If you're also using it through an IDE's built-in agent panel — I use Zed — there's an extra step, because the panel doesn't necessarily inherit your shell environment or your shell functions.</p>
<p>In Zed, the built-in Claude Agent is installed from the ACP Registry, and registry-installed agents are locked to a single instance — you can't just duplicate the entry under a new name and expect it to behave differently. Instead, add two <strong>custom</strong> entries that each launch Claude Code's ACP adapter directly, with their own <code>CLAUDE_CONFIG_DIR</code>:</p>
<pre><code class="language-json">{
  "agent_servers": {
    "Claude Agent (Personal)": {
      "type": "custom",
      "command": "npx",
      "args": ["@agentclientprotocol/claude-agent-acp@latest", "--acp"],
      "env": {
        "CLAUDE_CONFIG_DIR": "/Users/you/.claude-personal"
      }
    },
    "Claude Agent (Work)": {
      "type": "custom",
      "command": "npx",
      "args": ["@agentclientprotocol/claude-agent-acp@latest", "--acp"],
      "env": {
        "CLAUDE_CONFIG_DIR": "/Users/you/.claude-work"
      }
    }
  }
}
</code></pre>
<p>Now the Agent Panel's new-thread menu shows two named agents instead of one generic one. Pick the right one when you start a thread, <code>/login</code> each the first time, and you're set. This is honestly a little safer than the terminal aliases — you're explicitly picking an account from a list each time, instead of relying on muscle memory.</p>
<h2>Usage cheat sheet</h2>
<table>
<thead>
<tr>
<th>Context</th>
<th>Command / selection</th>
<th>Account</th>
</tr>
</thead>
<tbody><tr>
<td>Terminal</td>
<td><code>claude-personal</code></td>
<td>Personal</td>
</tr>
<tr>
<td>Terminal</td>
<td><code>claude-work</code></td>
<td>Work</td>
</tr>
<tr>
<td>Terminal, inside a <code>direnv</code>-tagged repo</td>
<td>plain <code>claude</code></td>
<td>Work (automatic)</td>
</tr>
<tr>
<td>Zed Agent Panel</td>
<td>"Claude Agent (Personal)"</td>
<td>Personal</td>
</tr>
<tr>
<td>Zed Agent Panel</td>
<td>"Claude Agent (Work)"</td>
<td>Work</td>
</tr>
</tbody></table>
<h2>Wrapping up</h2>
<ul>
<li><p><code>CLAUDE_CONFIG_DIR</code> gives you fully isolated Claude Code accounts — separate credentials, separate session history — by pointing each one at its own folder.</p>
</li>
<li><p>Don't symlink the two accounts' history together, even though it's tempting. It defeats the point of keeping them separate in the first place.</p>
</li>
<li><p>Shell aliases solve this for the terminal, but they can't enforce anything — <code>direnv</code> can, if you want the switch to happen automatically instead of relying on memory.</p>
</li>
<li><p>If you're also using an IDE's agent panel, check whether it actually inherits your shell environment. In Zed's case it doesn't, so the account split needs to be configured separately as two named <code>agent_servers</code> entries.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[React: Function References vs Function Calls]]></title><description><![CDATA[In React code, you may see the following ways of calling functions in jsx elements:
onClick={handleClick}

onClick={() => handleClick()}

Understanding the difference and when to use which pattern is a common point of confusion. Let’s unpack what’s r...]]></description><link>https://blog.kellenbaker.com/react-function-references-vs-function-calls</link><guid isPermaLink="true">https://blog.kellenbaker.com/react-function-references-vs-function-calls</guid><category><![CDATA[React]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Fri, 10 Oct 2025 16:58:14 GMT</pubDate><content:encoded><![CDATA[<p>In React code, you may see the following ways of calling functions in jsx elements:</p>
<pre><code class="lang-javascript">onClick={handleClick}

onClick={<span class="hljs-function">() =&gt;</span> handleClick()}
</code></pre>
<p>Understanding the difference and when to use which pattern is a common point of confusion. Let’s unpack what’s really going on, and what React is doing with the function you give it.</p>
<h2 id="heading-function-reference-vs-function-call">Function Reference vs Function Call</h2>
<p>JavaScript has <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/First-class_Function">first-class functions</a>, meaning they can be called with <code>()</code> or passed around as variables (without <code>()</code>). Let’s illustrate this with a simple function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sayHi</span>(<span class="hljs-params"></span>) </span>{
   <span class="hljs-keyword">return</span> <span class="hljs-string">"hi"</span>;
}

sayHi(); <span class="hljs-comment">// "hi"</span>

<span class="hljs-comment">// or we can pass a reference to this function into another function:</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params">fn, name</span>) </span>{
  <span class="hljs-built_in">console</span>.log(fn() + <span class="hljs-string">" "</span> + name);
}

greet(sayHi, <span class="hljs-string">"Joe"</span>); <span class="hljs-comment">// "hi Joe"</span>
</code></pre>
<p>In the <code>greet</code> function, we’ve passed a <strong>reference</strong> (without parentheses) to the <code>sayHi</code> function. This <code>sayHi</code> function is then <strong>called</strong> (with parentheses) when the <code>greet</code> function is invoked. The key idea is:</p>
<ul>
<li><p><code>sayHi</code> → “Here’s the function.”</p>
</li>
<li><p><code>sayHi()</code> → “Run the function <em>now</em>.”</p>
</li>
</ul>
<h2 id="heading-what-react-does-with-onclick">What React does with <code>onClick</code></h2>
<p>React expects a function reference, not a function call. For example:</p>
<pre><code class="lang-javascript">&lt;button onClick={sayHi}&gt;Click&lt;/button&gt;
</code></pre>
<p>React will store the <strong>reference</strong> to the <code>sayHi</code> function so that <em>later</em>, when the button is clicked, it will run <code>sayHi(event)</code>. This is the normal, intended way to tell React to run a function when the button is clicked.</p>
<p>If instead you wrote:</p>
<pre><code class="lang-javascript">&lt;button onClick={sayHi()}&gt;Click&lt;/button&gt;
</code></pre>
<p>you would see the <code>sayHi</code> function run <em>immediately</em> when rendered instead of waiting for the click.</p>
<h2 id="heading-arrow-functions">Arrow functions</h2>
<p>It’s also common to use arrow functions in React event handlers. Let’s illustrate this example using the <code>greet</code> function from earlier:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params">name</span>) </span>{
  alert(<span class="hljs-string">`Hello, <span class="hljs-subst">${name}</span>!`</span>);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">GreetingExample</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [name, setName] = useState(<span class="hljs-string">""</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
        <span class="hljs-attr">value</span>=<span class="hljs-string">{name}</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter your name"</span>
        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setName(e.target.value)}
      /&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> greet(name)}&gt;Click<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>This function needs to pass an argument, <code>name</code>. But we can’t write it like this:</p>
<pre><code class="lang-javascript">&lt;button onClick={greet(name)}&gt;Click&lt;/button&gt;
</code></pre>
<p>because that would <em>call</em> <code>greet(name)</code> <strong>immediately during render</strong>, not when the user clicks.<br />The arrow function solves this by giving React a <strong>function reference</strong>: a small wrapper function that React can call <em>later</em> when the click actually happens. In this pattern, the arrow function <em>creates a new function each render</em>, but that’s perfectly fine for most cases. Here’s how that happens step by step:  </p>
<ol>
<li><p>React renders the button and stores the arrow function as the click handler.</p>
</li>
<li><p>When the button is clicked, React runs the arrow function.</p>
</li>
<li><p>The arrow function <em>then</em> calls <code>greet(name)</code> with the latest <code>name</code> value.</p>
</li>
</ol>
<p>Pop quiz moment — what would happen if you tried this:</p>
<pre><code class="lang-javascript">&lt;button onClick={<span class="hljs-function">() =&gt;</span> sayHi}&gt;Click&lt;/button&gt;
</code></pre>
<p>If you thought “nothing,” you are correct! <strong>Nothing</strong> would happen in this example because the arrow function receives a <strong>reference</strong> to <code>sayHi</code>, but does NOT invoke it!</p>
<h2 id="heading-analogy">Analogy</h2>
<p>Think of this like giving React your phone number.</p>
<ul>
<li><p><code>onClick={fn}</code> → You give React your number. React dials it later.</p>
</li>
<li><p><code>onClick={fn()}</code> → You dial the phone number <em>right now</em>, and give React the <em>result of the call</em>.</p>
</li>
<li><p><code>onClick={() =&gt; fn}</code> → You give React a <em>note</em> that says “here’s the number" — but the number is never dialed, and React never makes the call.</p>
</li>
</ul>
<h2 id="heading-when-to-use-which">When to use which</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>When to use</td><td>Example</td><td>Why</td></tr>
</thead>
<tbody>
<tr>
<td>You don’t need arguments</td><td><code>onClick={handleClick}</code></td><td>Simpler and avoids creating a new function on each render</td></tr>
<tr>
<td>You need arguments or extra logic</td><td><code>onClick={() =&gt; handleClick(id)}</code></td><td>Lets you call your function with arguments when clicked</td></tr>
<tr>
<td>❌ Don’t do this</td><td><code>onClick={handleClick()}</code></td><td>Calls immediately during render</td></tr>
<tr>
<td>❌ Or this</td><td><code>onClick={() =&gt; handleClick}</code></td><td>Returns a function, doesn’t call it</td></tr>
</tbody>
</table>
</div><h2 id="heading-wrapping-up">Wrapping up</h2>
<p>React doesn’t magically call functions — it simply calls whatever function reference you hand it when an event occurs. Understanding that difference between a <strong>function reference</strong> (<code>fn</code>) and a <strong>function call</strong> (<code>fn()</code>) explains nearly every “why doesn’t my onClick work?” moment.</p>
<p>When in doubt:</p>
<ul>
<li><p>Pass a <strong>function reference</strong> when you just need to call it later.</p>
</li>
<li><p>Use an <strong>arrow function</strong> when you need to pass arguments or do extra work.</p>
</li>
<li><p>Never call the function directly inside JSX unless you explicitly want it to run during render (rare!).</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[The Ruby Koans: About Class Methods]]></title><description><![CDATA[The Ruby Koans are a fantastic resource to introducing the concepts and syntax of the Ruby programming language. In this post, we’ll explore the concepts posed by about_class_methods.rb: class methods, instance methods, and singleton methods.
Objects...]]></description><link>https://blog.kellenbaker.com/the-ruby-koans-about-class-methods</link><guid isPermaLink="true">https://blog.kellenbaker.com/the-ruby-koans-about-class-methods</guid><category><![CDATA[Ruby]]></category><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Mon, 10 Feb 2025 16:39:50 GMT</pubDate><content:encoded><![CDATA[<p>The Ruby Koans are a fantastic resource to introducing the concepts and syntax of the Ruby programming language. In this post, we’ll explore the concepts posed by <code>about_class_methods.rb</code>: class methods, instance methods, and singleton methods.</p>
<h2 id="heading-objects-classes-and-class-objects"><strong>Objects, Classes, and Class Objects</strong></h2>
<p>Let's start with some fundamental truths:</p>
<ul>
<li><p><strong>Instances of a class are objects.</strong></p>
</li>
<li><p><strong>A class itself is an instance of</strong> <code>Class</code><strong>.</strong></p>
</li>
<li><p><strong>Since classes are objects, they can have their own methods.</strong></p>
</li>
</ul>
<h3 id="heading-objects-are-instances-of-a-class"><strong>Objects are instances of a class</strong></h3>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span></span>
<span class="hljs-keyword">end</span>

fido = Dog.new
puts fido.is_a?(Object)  <span class="hljs-comment"># =&gt; true</span>
</code></pre>
<p>Every object in Ruby inherits from <code>Object</code>, so even instances of <code>Dog</code> are objects.</p>
<h3 id="heading-classes-are-objects-too"><strong>Classes are objects too</strong></h3>
<pre><code class="lang-ruby">puts Dog.is_a?(Class)  <span class="hljs-comment"># =&gt; true</span>
puts Dog.is_a?(Object) <span class="hljs-comment"># =&gt; true</span>
</code></pre>
<p>Since <code>Dog</code> itself is an instance of <code>Class</code>, it is both a <strong>class</strong> and an <strong>object</strong> at the same time.</p>
<h2 id="heading-instance-methods-vs-class-methods"><strong>Instance Methods vs. Class Methods</strong></h2>
<p>Instance methods are methods that belong to a specific instance of a class and operate on that instance’s data, whereas class methods belong to the class itself and can be called without creating an instance.</p>
<h3 id="heading-defining-an-instance-method"><strong>Defining an Instance Method</strong></h3>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span></span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wag</span></span>
    <span class="hljs-symbol">:instance_level_wag</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>

fido = Dog.new
puts fido.wag  <span class="hljs-comment"># =&gt; :instance_level_wag</span>
</code></pre>
<p>Here, <code>wag</code> is an <strong>instance method</strong>. Each instance of <code>Dog</code> (e.g., <code>fido</code>) can call this method.</p>
<h3 id="heading-defining-a-class-method"><strong>Defining a Class Method</strong></h3>
<p>There are multiple ways to define class methods:</p>
<h4 id="heading-using-selfmethodname"><strong>Using</strong> <code>self.method_name</code></h4>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span></span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">self</span>.<span class="hljs-title">class_method</span></span>
    <span class="hljs-symbol">:dogs_class_method</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>

puts Dog.class_method  <span class="hljs-comment"># =&gt; :dogs_class_method</span>
</code></pre>
<p>By using <code>self.</code> inside the class definition, we define a <strong>class method</strong> directly on <code>Dog</code>.</p>
<h4 id="heading-using-class-ltlt-self-singleton-class-syntax"><strong>Using</strong> <code>class &lt;&lt; self</code> <strong>(Singleton Class Syntax)</strong></h4>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span></span>
  <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;&lt; self</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">another_class_method</span></span>
      <span class="hljs-symbol">:still_another_way</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>

puts Dog.another_class_method  <span class="hljs-comment"># =&gt; :still_another_way</span>
</code></pre>
<p>This technique defines class methods using the singleton class, which is a special, hidden class that Ruby creates for each object to hold methods specific to that object. A singleton class (also called a metaclass or eigenclass) is unique to each object and allows defining methods that only that particular object can access. In this case, <code>class &lt;&lt; self</code> opens up the singleton class of <code>Dog</code>, allowing us to define methods that belong only to the <code>Dog</code> class itself.</p>
<p>For example:</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span></span>
  <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;&lt; self</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">bark</span></span>
      <span class="hljs-string">'Woof!'</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>

puts Dog.bark  <span class="hljs-comment"># =&gt; 'Woof!'</span>
</code></pre>
<p>This is equivalent to:</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span></span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">self</span>.<span class="hljs-title">bark</span></span>
    <span class="hljs-string">'Woof!'</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>

puts Dog.bark  <span class="hljs-comment"># =&gt; 'Woof!'</span>
</code></pre>
<p>Singleton methods can also be applied to individual instances:</p>
<pre><code class="lang-ruby">fido = Dog.new

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fido</span>.<span class="hljs-title">speak</span></span>
  <span class="hljs-string">'Arf!'</span>
<span class="hljs-keyword">end</span>

puts fido.speak  <span class="hljs-comment"># =&gt; 'Arf!'</span>
</code></pre>
<p>However, this method is only available to <code>fido</code>, not other instances of <code>Dog</code>.</p>
<h2 id="heading-singleton-methods-on-objects"><strong>Singleton Methods on Objects</strong></h2>
<p>Since everything in Ruby is an object, we can define methods on individual instances:</p>
<pre><code class="lang-ruby">fido = Dog.new

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fido</span>.<span class="hljs-title">wag</span></span>
  <span class="hljs-symbol">:fidos_wag</span>
<span class="hljs-keyword">end</span>

puts fido.wag  <span class="hljs-comment"># =&gt; :fidos_wag</span>
</code></pre>
<p>However, this method <strong>only applies to</strong> <code>fido</code>, not other <code>Dog</code> instances:</p>
<pre><code class="lang-ruby">rover = Dog.new
puts rover.wag  <span class="hljs-comment"># =&gt; NoMethodError</span>
</code></pre>
<h2 id="heading-class-instance-variables-vs-instance-variables"><strong>Class Instance Variables vs. Instance Variables</strong></h2>
<p>Instance variables inside a class belong to <strong>instances of that class</strong>, whereas instance variables inside the class definition itself belong to the <strong>class object</strong>.</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span></span>
  <span class="hljs-keyword">attr_accessor</span> <span class="hljs-symbol">:name</span>
<span class="hljs-keyword">end</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">Dog</span>.<span class="hljs-title">name</span></span>
  @name
<span class="hljs-keyword">end</span>

fido = Dog.new
fido.name = <span class="hljs-string">"Fido"</span>

puts fido.name  <span class="hljs-comment"># =&gt; "Fido"</span>
puts Dog.name   <span class="hljs-comment"># =&gt; nil</span>
</code></pre>
<p>The instance variable <code>@name</code> on <code>fido</code> does not affect <code>Dog</code> because <code>Dog.name</code> refers to an <strong>instance variable on the class object</strong>, not on an instance.</p>
<h2 id="heading-the-value-of-self-in-a-class-definition"><strong>The Value of</strong> <code>self</code> <strong>in a Class Definition</strong></h2>
<p>Inside a class definition, <code>self</code> refers to the class itself:</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span></span>
  puts <span class="hljs-keyword">self</span>  <span class="hljs-comment"># =&gt; Dog</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>Since <code>self</code> refers to the class, we can define class methods like this:</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span></span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">self</span>.<span class="hljs-title">class_method2</span></span>
    <span class="hljs-symbol">:another_way_to_write_class_methods</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>

puts Dog.class_method2  <span class="hljs-comment"># =&gt; :another_way_to_write_class_methods</span>
</code></pre>
<h2 id="heading-returning-values-from-class-definitions"><strong>Returning Values from Class Definitions</strong></h2>
<p>In Ruby, the <strong>last expression</strong> inside a class definition determines its return value:</p>
<pre><code class="lang-ruby">LastExpression = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span></span>
                   <span class="hljs-number">21</span>
                 <span class="hljs-keyword">end</span>

puts LastExpression  <span class="hljs-comment"># =&gt; 21</span>
</code></pre>
<p>For example, this behavior can be used in metaprogramming to dynamically define constants or class-level settings based on computations performed within the class definition:</p>
<pre><code class="lang-ruby">DefaultLimit = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Configuration</span></span>
                 <span class="hljs-number">100</span> * <span class="hljs-number">2</span>
               <span class="hljs-keyword">end</span>

puts DefaultLimit  <span class="hljs-comment"># =&gt; 200</span>
</code></pre>
<p>Here, the last evaluated expression (<code>100 * 2</code>) is returned and assigned to <code>DefaultLimit</code>.</p>
<h2 id="heading-calling-class-methods-from-instances"><strong>Calling Class Methods from Instances</strong></h2>
<p>Although class methods belong to the class, instances can still access them indirectly:</p>
<pre><code class="lang-ruby">fido = Dog.new
puts fido.<span class="hljs-keyword">class</span>.another_class_method  <span class="hljs-comment"># =&gt; :still_another_way</span>
</code></pre>
<p>This works because <code>fido.class</code> evaluates to <code>Dog</code>, and <code>Dog.another_class_method</code> is a valid class method.</p>
<h2 id="heading-which-class-method-syntax-should-you-use"><strong>Which Class Method Syntax Should You Use?</strong></h2>
<p>Both of the following approaches work for defining class methods:</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Demo</span></span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">self</span>.<span class="hljs-title">method_one</span></span>
  <span class="hljs-keyword">end</span>

  <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;&lt; self</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">method_two</span></span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>Which one should you prefer?</p>
<ul>
<li><p><code>self.method_name</code> is more common and easier to read. This is usually what you should do.</p>
</li>
<li><p><code>class &lt;&lt; self</code> is useful when defining multiple class methods at once.</p>
</li>
</ul>
<p>Hopefully this post has clarified some key concepts in this chapter of the Koans. As you continue your Ruby journey, may you keep in mind (my personal favorite axiom from the test output): <code>mountains are merely mountains</code>.</p>
]]></content:encoded></item><item><title><![CDATA[How to Create a Dynamic Timezone Clock Component in Vue with Day.js]]></title><description><![CDATA[In this tutorial, we'll build a lightweight, reusable Vue.js component that displays the current time in any specified timezone. This component will automatically update every second and handle timezone conversions seamlessly.
Prerequisites

Basic kn...]]></description><link>https://blog.kellenbaker.com/how-to-create-a-dynamic-timezone-clock-component-in-vue-with-dayjs</link><guid isPermaLink="true">https://blog.kellenbaker.com/how-to-create-a-dynamic-timezone-clock-component-in-vue-with-dayjs</guid><category><![CDATA[Vue.js]]></category><category><![CDATA[dayjs]]></category><category><![CDATA[timezone]]></category><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Tue, 17 Dec 2024 20:20:14 GMT</pubDate><content:encoded><![CDATA[<p>In this tutorial, we'll build a lightweight, reusable Vue.js component that displays the current time in any specified timezone. This component will automatically update every second and handle timezone conversions seamlessly.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><p>Basic knowledge of Vue.js</p>
</li>
<li><p>Node.js and npm installed</p>
</li>
<li><p>Vue 3 with Composition API</p>
</li>
</ul>
<h2 id="heading-step-1-set-up-a-new-vue-project">Step 1: Set Up a New Vue Project</h2>
<p>First, let's create a new Vue project using Vite:</p>
<pre><code class="lang-bash">npm create vite@latest timezone-clock -- --template vue
<span class="hljs-built_in">cd</span> timezone-clock
npm install
</code></pre>
<h2 id="heading-step-2-install-required-dependencies">Step 2: Install Required Dependencies</h2>
<p>We'll use <code>dayjs</code> for timezone handling:</p>
<pre><code class="lang-bash">npm install dayjs
</code></pre>
<h2 id="heading-understanding-timezone-handling">Understanding Timezone Handling</h2>
<p>Before we dive into the code, let's break down why we need additional libraries for timezone management:</p>
<ul>
<li><p>JavaScript's native <code>Date</code> object doesn't provide robust timezone conversion</p>
</li>
<li><p><code>dayjs</code> with its UTC and timezone plugins allows easy, accurate timezone transformations</p>
</li>
<li><p>The plugins extend dayjs's capabilities to parse, manipulate, and display times across different timezones</p>
</li>
</ul>
<h2 id="heading-step-3-create-the-timezone-clock-component">Step 3: Create the Timezone Clock Component</h2>
<p>Create a new file <code>TimezoneClock.vue</code> in your <code>src/components</code> directory:</p>
<pre><code class="lang-javascript">&lt;script setup&gt;
<span class="hljs-keyword">import</span> { computed, ref, onBeforeUnmount } <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;
<span class="hljs-keyword">import</span> dayjs <span class="hljs-keyword">from</span> <span class="hljs-string">'dayjs'</span>;
<span class="hljs-keyword">import</span> utc <span class="hljs-keyword">from</span> <span class="hljs-string">'dayjs/plugin/utc'</span>;
<span class="hljs-keyword">import</span> dayjsTimezone <span class="hljs-keyword">from</span> <span class="hljs-string">'dayjs/plugin/timezone'</span>;

<span class="hljs-comment">// Define component props</span>
<span class="hljs-keyword">const</span> props = defineProps({
  <span class="hljs-attr">timezone</span>: {
    <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,
    <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>,
  },
});

<span class="hljs-comment">// Extend dayjs with UTC and timezone plugins</span>
dayjs.extend(utc);
dayjs.extend(dayjsTimezone);

<span class="hljs-comment">// Reactive reference to current time</span>
<span class="hljs-keyword">const</span> currentTime = ref(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>());

<span class="hljs-comment">// Function to update current time</span>
<span class="hljs-keyword">const</span> updateCurrentTime = <span class="hljs-function">() =&gt;</span> {
  currentTime.value = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();
};

<span class="hljs-comment">// Computed property to format time in specified timezone</span>
<span class="hljs-keyword">const</span> formattedTime = computed(<span class="hljs-function">() =&gt;</span>
  dayjs(currentTime.value).tz(props.timezone).format(<span class="hljs-string">'h:mm a z'</span>)
);

<span class="hljs-comment">// Set up interval to update time every second</span>
<span class="hljs-keyword">const</span> updateTimeInterval = <span class="hljs-built_in">setInterval</span>(updateCurrentTime, <span class="hljs-number">1000</span>);

<span class="hljs-comment">// Clean up interval when component is unmounted</span>
onBeforeUnmount(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">clearInterval</span>(updateTimeInterval);
});
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>{{ formattedTime }}<span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span></span>
</code></pre>
<h2 id="heading-key-concepts-explained">Key Concepts Explained</h2>
<h3 id="heading-1-props-and-component-configuration">1. Props and Component Configuration</h3>
<ul>
<li><p><code>defineProps()</code> creates a prop called <code>timezone</code></p>
</li>
<li><p><code>required: true</code> ensures a timezone must be provided when using the component</p>
</li>
<li><p>Prop is typed as a <code>String</code> to accept timezone names like "America/New_York"</p>
</li>
</ul>
<h3 id="heading-2-reactive-time-management">2. Reactive Time Management</h3>
<ul>
<li><p><code>ref(new Date())</code> creates a reactive reference to the current time</p>
</li>
<li><p><code>updateCurrentTime()</code> updates this reference</p>
</li>
<li><p><code>setInterval()</code> calls this function every second, creating a "live" clock</p>
</li>
</ul>
<h3 id="heading-3-time-formatting-with-dayjs">3. Time Formatting with dayjs</h3>
<ul>
<li><p><code>dayjs().tz()</code> converts the current time to the specified timezone</p>
</li>
<li><p><code>.format('h:mm a z')</code> displays time as:</p>
<ul>
<li><p><code>h</code>: Hour in 12-hour format</p>
</li>
<li><p><code>mm</code>: Minutes</p>
</li>
<li><p><code>a</code>: AM/PM indicator</p>
</li>
<li><p><code>z</code>: Timezone abbreviation</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-4-cleanup-with-onbeforeunmount">4. Cleanup with onBeforeUnmount</h3>
<ul>
<li><p><code>clearInterval()</code> stops the timer when the component is removed</p>
</li>
<li><p>Prevents memory leaks and unnecessary background processes</p>
</li>
</ul>
<h2 id="heading-step-4-using-the-component">Step 4: Using the Component</h2>
<p>In your <code>App.vue</code>, demonstrate the component:</p>
<pre><code class="lang-javascript">&lt;script setup&gt;
<span class="hljs-keyword">import</span> TimezoneClock <span class="hljs-keyword">from</span> <span class="hljs-string">'@/components/TimezoneClock.vue'</span>;
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>World Clocks<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        New York: <span class="hljs-tag">&lt;<span class="hljs-name">TimezoneClock</span> <span class="hljs-attr">timezone</span>=<span class="hljs-string">"America/New_York"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
        London: <span class="hljs-tag">&lt;<span class="hljs-name">TimezoneClock</span> <span class="hljs-attr">timezone</span>=<span class="hljs-string">"Europe/London"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
        Tokyo: <span class="hljs-tag">&lt;<span class="hljs-name">TimezoneClock</span> <span class="hljs-attr">timezone</span>=<span class="hljs-string">"Asia/Tokyo"</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> 
 <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span></span>
</code></pre>
<h2 id="heading-advanced-tips">Advanced Tips</h2>
<ul>
<li><p>Always use IANA timezone names (like "America/New_York")</p>
</li>
<li><p>Handle potential timezone name errors with a default fallback</p>
</li>
<li><p>Consider adding props for custom date formatting</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You've now created a flexible, reactive timezone clock component in Vue.js. By leveraging dayjs and Vue's Composition API, we've built a powerful time display solution that's both performant and easy to use.</p>
<h3 id="heading-learning-challenges">Learning Challenges</h3>
<ol>
<li><p>Add a prop to customize the time format</p>
</li>
<li><p>Implement error handling for invalid timezones</p>
</li>
<li><p>Create a timezone selector feature</p>
</li>
</ol>
<p>Happy coding! 🕒✨</p>
]]></content:encoded></item><item><title><![CDATA[How to Rebase]]></title><description><![CDATA[Say you have a branch called hotfix. You originally started by branching off of develop, but this was accidental. You need to rebase this branch from develop to main to release it as a hot fix. Here's an easy-to-follow guide on how to do it:

On your...]]></description><link>https://blog.kellenbaker.com/how-to-rebase</link><guid isPermaLink="true">https://blog.kellenbaker.com/how-to-rebase</guid><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Wed, 22 May 2024 21:48:17 GMT</pubDate><content:encoded><![CDATA[<p>Say you have a branch called <code>hotfix</code>. You originally started by branching off of <code>develop</code>, but this was accidental. You need to rebase this branch from <code>develop</code> to <code>main</code> to release it as a hot fix. Here's an easy-to-follow guide on how to do it:</p>
<ol>
<li><p>On your <code>hotfix</code> branch, run <code>git rebase develop</code> .</p>
</li>
<li><p>You may see merge conflicts. These may need to be resolved. You will need to use your best judgement here, as it is always specific to the codebase and the branch. In my experience, I see this really commonly with database schema updates.</p>
</li>
<li><p>After you resolve conflicts, DO NOT push/pull.</p>
</li>
<li><p>Check out <code>main</code> and <code>git pull</code> to make sure you have the most up-to-date changes there.</p>
</li>
<li><p>Back on <code>hotfix</code> branch, run <code>git rebase --onto main develop</code>. This is saying: <code>git rebase --onto &lt;new-branch&gt; &lt;old-branch&gt;</code>.</p>
</li>
<li><p>You'll probably see some diff in the push/pull section. Don't pull.</p>
</li>
<li><p>Instead, force push: <code>git push origin hotfix --force</code>.</p>
</li>
<li><p>If you already have a PR open for this branch, you may see a bunch of commits that don't belong to you. In GitHub (or wherever your code lives), you will need to point the merge branch toward <code>main</code>. The commits that don't belong to you should disappear, and only your commits should be left.</p>
</li>
<li><p>If you don't have a PR open already, open one to <code>main</code>.</p>
</li>
</ol>
<blockquote>
<p>To rebase a hotfix branch from develop to main, first rebase onto develop and resolve any conflicts. Then, update main and rebase the hotfix branch onto main. Finally, force push the changes and adjust any open PRs to point to main.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Becoming a Ruby on Rails Developer]]></title><description><![CDATA[I am approaching a one-year work anniversary at an awesome, creative company that uses Ruby on Rails to do some incredible stuff. I will admit that I was hesitant at first -- I have heard many developers online and IRL comment on how the language and...]]></description><link>https://blog.kellenbaker.com/becoming-a-ruby-on-rails-developer</link><guid isPermaLink="true">https://blog.kellenbaker.com/becoming-a-ruby-on-rails-developer</guid><category><![CDATA[Ruby]]></category><category><![CDATA[Ruby on Rails]]></category><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Wed, 25 Jan 2023 16:46:42 GMT</pubDate><content:encoded><![CDATA[<p>I am approaching a one-year work anniversary at an awesome, creative company that uses Ruby on Rails to do some incredible stuff. I will admit that I was hesitant at first -- I have heard many developers online and IRL comment on how the language and framework are outdated, long since replaced with more powerful alternatives. I don't think those people have any idea what they're talking about. Ruby on Rails is a flexible, fast, and scalable tool that is quietly powering some of the most popular sites on the web.</p>
<p>Here's what to expect if you're getting started on your Ruby on Rails journey.</p>
<h3 id="heading-there-is-a-learning-curve">There is a learning curve</h3>
<p>Ruby looks and behaves differently from any other programming language I've dealt with. At first, it can be very difficult to look at a bit of Ruby code and understand what is going on. You will see <a target="_blank" href="https://www.rubyguides.com/2018/02/ruby-symbols/">symbols</a> all over the place, which can be a big concept to wrap your head around. (<code>:symbols</code> look <code>:like_this</code>.) <a target="_blank" href="https://www.rubyguides.com/2020/05/ruby-hash-methods/">Hashes</a> are sort of like objects in JavaScript, but not really. (<code>{ :key =&gt; 'value' }</code>)</p>
<p>One of the biggest reasons for the learning curve is that...</p>
<h3 id="heading-there-are-many-ways-to-do-things">There are many ways to do things</h3>
<p>You can push things into an array like this:</p>
<pre><code class="lang-ruby">array = Array.new
array.push(<span class="hljs-number">1</span>)
<span class="hljs-comment"># OR</span>
array &lt;&lt; <span class="hljs-number">1</span>
</code></pre>
<p>You can call a method with or without parentheses:</p>
<pre><code class="lang-ruby"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_global_method</span><span class="hljs-params">(a,b)</span></span>
  a + b
<span class="hljs-keyword">end</span>

...

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_calling_global_methods</span></span>
  assert_equal <span class="hljs-number">5</span>, my_global_method(<span class="hljs-number">2</span>,<span class="hljs-number">3</span>)
<span class="hljs-keyword">end</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_calling_global_methods_without_parentheses</span></span>
  result = my_global_method <span class="hljs-number">2</span>, <span class="hljs-number">3</span>
  assert_equal <span class="hljs-number">5</span>, result
<span class="hljs-keyword">end</span>
</code></pre>
<p>You can even iterate through an array with a completely different syntax:</p>
<pre><code class="lang-ruby">  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_iterating_with_each</span></span>
    array = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
    sum = <span class="hljs-number">0</span>
    array.each <span class="hljs-keyword">do</span> <span class="hljs-params">|item|</span>
      sum += item
    <span class="hljs-keyword">end</span>
    assert_equal <span class="hljs-number">6</span>, sum
  <span class="hljs-keyword">end</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_each_can_use_curly_brace_blocks_too</span></span>
    array = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
    sum = <span class="hljs-number">0</span>
    array.each { <span class="hljs-params">|item|</span> sum += item }
    assert_equal <span class="hljs-number">6</span>, sum
  <span class="hljs-keyword">end</span>
</code></pre>
<p>The examples above were taken from the <a target="_blank" href="https://www.rubykoans.com/">Ruby Koans.</a> These exercises are hands down the best way to get familiar with the way Ruby works. If you are an aspiring Ruby developer, start here.</p>
<h3 id="heading-community-is-key">Community is key</h3>
<p>Finding good documentation or tutorials for Ruby or Ruby on Rails can feel like hunting through an ancient library for esoteric forbidden knowledge. There is a lot of garbage out there, a lot of outdated information, and a lot of different viewpoints. More than any other language I've worked in, it is important to find resources and people who you trust. Your best resource will most likely be the development team you are working with.</p>
<p>Here are some resources I suggest:</p>
<ul>
<li><p><a target="_blank" href="https://guides.rubyonrails.org/">RailsGuides</a></p>
</li>
<li><p><a target="_blank" href="https://www.rubyguides.com/">RubyGuides</a></p>
</li>
<li><p><a target="_blank" href="https://www.superhi.com/courses/ruby-on-rails">SuperHi Ruby on Rails course</a></p>
</li>
</ul>
<h3 id="heading-everything-is-an-object">Everything is an object</h3>
<p>Another example from the Koans...</p>
<pre><code class="lang-ruby">  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_everything_is_an_object</span></span>
    assert_equal <span class="hljs-literal">true</span>, <span class="hljs-number">1</span>.is_a?(Object)
    assert_equal <span class="hljs-literal">true</span>, <span class="hljs-number">1.5</span>.is_a?(Object)
    assert_equal <span class="hljs-literal">true</span>, <span class="hljs-string">"string"</span>.is_a?(Object)
    assert_equal <span class="hljs-literal">true</span>, <span class="hljs-literal">nil</span>.is_a?(Object)
    assert_equal <span class="hljs-literal">true</span>, Object.is_a?(Object)
  <span class="hljs-keyword">end</span>
</code></pre>
<p>In Ruby, everything is an object. This is part of the magic.</p>
<p>In <a target="_blank" href="https://www.amazon.com/gp/product/0134456475/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0134456475&amp;linkCode=as2&amp;tag=sandimetzcom-20&amp;linkId=426bd331ea480076fa612b329d46cd14">Practical Object-Oriented Design</a>, author Sandi Metz describes the world as object-oriented:</p>
<blockquote>
<p>The objects with which you interact might include a spouse and a cat, or an old car and a pile of bike parts in the garage, or your ticking heart and the exercise plan you use to keep it healthy. Each of these objects comes equipped with its own behavior, and while some of the interactions between them might be predictable, it is entirely possible for your spouse to unexpectedly step on the cat, causing a reaction that rapidly raises everyone's heart rate and gives you new appreciation for your exercise regimen.</p>
<p>...</p>
<p>Failures of OOD [object-oriented design] might look like failures of coding technique, but they are actually failures of perspective.</p>
</blockquote>
<p>Coding in Ruby and working with Rails will give you a whole new perspective. It's been quite the journey, and I still feel like I'm at the very beginning of a whole new world.</p>
]]></content:encoded></item><item><title><![CDATA[using sass variables in vue data]]></title><description><![CDATA[If you have a .scss file that stores your project's colors, you can easily reference those values in Vue. I recently ran into this issue when using a third-party library that required styling information to be set in data(). Overriding the default st...]]></description><link>https://blog.kellenbaker.com/using-sass-variables-in-vue-data</link><guid isPermaLink="true">https://blog.kellenbaker.com/using-sass-variables-in-vue-data</guid><category><![CDATA[Sass]]></category><category><![CDATA[scss]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Vue.js]]></category><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Thu, 14 Jul 2022 15:58:32 GMT</pubDate><content:encoded><![CDATA[<p>If you have a <code>.scss</code> file that stores your project's colors, you can easily reference those values in Vue. I recently ran into this issue when using a third-party library that required styling information to be set in <code>data()</code>. Overriding the default styles in this library using <code>::v-deep</code> was not an option because of the complexity of how this component renders. Luckily, importing sass variables to your javascript is really simple.</p>
<p>In your sass file, provide an <code>:export</code> object:</p>
<pre><code class="lang-scss">:export {
  Red: <span class="hljs-variable">$red</span>;
  Orange: <span class="hljs-variable">$orange</span>;
  Deepyellow: <span class="hljs-variable">$deepyellow</span>;
  Canary: <span class="hljs-variable">$canary</span>;
  Black: <span class="hljs-variable">$black</span>;
}
</code></pre>
<p>Then, in your Vue component, you can import these styles:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">'@src/styles.scss'</span>;
</code></pre>
<p>You can then access these styles throughout the Vue component. In my case, I needed to set colors in <code>data()</code> like this:</p>
<pre><code class="lang-javascript">data() {
   <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">eventDataTransform</span>: <span class="hljs-function"><span class="hljs-params">eventData</span> =&gt;</span> {
          <span class="hljs-keyword">return</span> {
              <span class="hljs-attr">title</span>: eventData.title,
              <span class="hljs-attr">start</span>: eventData.start,
              <span class="hljs-attr">end</span>: eventData.end,
              <span class="hljs-attr">borderColor</span>: styles.Black,
              <span class="hljs-attr">textColor</span>: styles.Black,
              <span class="hljs-attr">color</span>: styles.Canary,
          }
     }
},
</code></pre>
<p>If you have a ton of variables in your <code>styles.css</code> file, you might not want to import all of them. You can import just the ones you need like this:</p>
<pre><code class="lang-ruby">import { Black, Red } from <span class="hljs-string">'@src/styles.scss'</span>;
</code></pre>
]]></content:encoded></item><item><title><![CDATA[TIL: convert a string into an array of words in JS]]></title><description><![CDATA[Sometimes it's nice to document the little wins. Today, I learned this useful bit of code to parse a string into an array of words, while removing punctuation.
text.replace(/\p{P}/gu, "").split(" "))
To break this down:

text: the string to parse
.re...]]></description><link>https://blog.kellenbaker.com/til-convert-a-string-into-an-array-of-words-in-js</link><guid isPermaLink="true">https://blog.kellenbaker.com/til-convert-a-string-into-an-array-of-words-in-js</guid><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Fri, 03 Jun 2022 18:48:12 GMT</pubDate><content:encoded><![CDATA[<p>Sometimes it's nice to document the little wins. Today, I learned this useful bit of code to parse a string into an array of words, while removing punctuation.</p>
<p><code>text.replace(/\p{P}/gu, "").split(" "))</code></p>
<p>To break this down:</p>
<ul>
<li><code>text</code>: the string to parse</li>
<li><code>.replace</code>: a JavaScript function </li>
<li><code>/\p{P}/gu, ""</code>: regex that informs <code>replace</code> to remove all punctuation and replace it with nothing</li>
<li><code>.split(" ")</code>: a JavaScript function that breaks a string into an array based on the character passed into the function. In this case, it will <code>split</code> the string whenever there is a space.</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[5 Sonic Pi Tips]]></title><description><![CDATA[Here are five tricks I reach for when making music with Sonic Pi. 
1. :sync to a metronome
Keep your live loops in sync by creating a metronome: 
live_loop :click do
  sleep 1
end
Use :sync to keep all your loops together with the :click:
live_loop :...]]></description><link>https://blog.kellenbaker.com/5-sonic-pi-tips</link><guid isPermaLink="true">https://blog.kellenbaker.com/5-sonic-pi-tips</guid><category><![CDATA[Ruby]]></category><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Tue, 05 Apr 2022 14:12:26 GMT</pubDate><content:encoded><![CDATA[<p>Here are five tricks I reach for when making music with Sonic Pi. </p>
<h2 id="heading-1-sync-to-a-metronome">1. <code>:sync</code> to a metronome</h2>
<p>Keep your live loops in sync by creating a metronome: </p>
<pre><code>live_loop <span class="hljs-symbol">:click</span> <span class="hljs-keyword">do</span>
  sleep <span class="hljs-number">1</span>
<span class="hljs-keyword">end</span>
</code></pre><p>Use <code>:sync</code> to keep all your loops together with the <code>:click</code>:</p>
<pre><code>live_loop <span class="hljs-symbol">:kick</span>, <span class="hljs-symbol">sync:</span> <span class="hljs-symbol">:click</span> <span class="hljs-keyword">do</span> stop
  sample <span class="hljs-symbol">:bd_808</span>
  sleep <span class="hljs-number">1</span>
<span class="hljs-keyword">end</span>
</code></pre><h2 id="heading-2-move-things-along-with-tick">2.  move things along with <code>.tick</code></h2>
<blockquote>
<p>Increment the default tick by 1 and return value. Successive calls to tick will continue to increment the default tick.</p>
</blockquote>
<p><code>.tick</code> is a handy shorthand for playing melodies. Essentially, it can be used to "tick" through an array of values, moving to the next item in the array on the next repeat.</p>
<p>Let's say you have a simple melody consisting of four notes: 
<code>[:c3, :a2, :c3, :e3]</code></p>
<p>You can play these notes in order using <code>tick</code>:</p>
<p><code>play [:c3, :a2, :c3, :e3].tick</code></p>
<p>I also like to use this to set <code>sleep</code> values for varied but predictable rhythms:</p>
<p><code>sleep [0.5, 0.75, 0.25, 0.25, 0.5].tick</code></p>
<h2 id="heading-3-make-the-computer-choose-for-you">3. make the computer <code>.choose</code> for you</h2>
<p>IMO, randomization is probably the most important aspects of creating algorithmically generated music. <code>.choose</code> is a simple way to get the computer to "choose" something for you. It will randomly pick a value from the provided array. Here is an example of a bassline I created with this method: </p>
<pre><code>live_loop <span class="hljs-symbol">:earth</span>, <span class="hljs-symbol">sync:</span> <span class="hljs-symbol">:met</span> <span class="hljs-keyword">do</span>
  with_fx <span class="hljs-symbol">:echo</span> <span class="hljs-keyword">do</span>
    use_synth <span class="hljs-symbol">:beep</span>
    play [<span class="hljs-symbol">:c3</span>, <span class="hljs-symbol">:a2</span>].choose, <span class="hljs-symbol">attack:</span> <span class="hljs-number">2</span>, <span class="hljs-symbol">decay:</span> <span class="hljs-number">3</span>, <span class="hljs-symbol">release:</span> <span class="hljs-number">2</span>
    sleep <span class="hljs-number">6</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre><p>You'll never know if this is going to play a C or an A until it actually happens -- it really helps add a mysterious, unpredictable, and constantly evolving vibe.</p>
<h2 id="heading-4-dice-things-up">4. <code>dice</code> things up</h2>
<blockquote>
<p>Throws a dice with the specified num_sides (defaults to 6) and returns the score as a number between 1 and num_sides. </p>
</blockquote>
<p>More randomization! Instead of choosing from a set of pre-specified values, this function literally acts like a throw of a die. </p>
<p>I like to use this to trigger random percussion samples to add some ear candy or variation to the beat. </p>
<pre><code>live_loop <span class="hljs-symbol">:perc</span> <span class="hljs-keyword">do</span>
  <span class="hljs-keyword">if</span> dice == <span class="hljs-number">1</span>
    with_fx <span class="hljs-symbol">:ping_pong</span> <span class="hljs-keyword">do</span>
      sample <span class="hljs-symbol">:perc_snap</span>, <span class="hljs-symbol">amp:</span> <span class="hljs-number">0</span>.<span class="hljs-number">5</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
  sleep <span class="hljs-number">1</span>
<span class="hljs-keyword">end</span>
</code></pre><h2 id="heading-5-get-euclidian-with-spread">5. Get Euclidian with <code>spread</code></h2>
<blockquote>
<p>Creates a new ring of boolean values which space a given number of accents as evenly as possible throughout a bar. </p>
</blockquote>
<p>Ok this one is sick AF. This will create <a target="_blank" href="https://blog.landr.com/euclidean-rhythms/">Euclidian</a> rhythms based on the parameters provided. Essentially, this is a fancy way of saying that <code>x</code> number of notes will be spread as evenly as possible across <code>y</code> number of beats. This concept is named after the ancient homie Euclid, who described the mathematical relationship performed here.</p>
<p>This is a super easy way to generate interesting polyrhythms: </p>
<pre><code><span class="hljs-attribute">live_loop</span> :bd do
  <span class="hljs-attribute">sample</span> :bd_<span class="hljs-number">808</span> if (spread <span class="hljs-number">2</span>, <span class="hljs-number">5</span>).tick
  <span class="hljs-attribute">sleep</span> <span class="hljs-number">0</span>.<span class="hljs-number">25</span>
<span class="hljs-attribute">end</span>
</code></pre><p>This will perform two kicks across the space of 5 sixteenth notes. There are so many cool possibilities to find here by rearranging these numbers. Just go play around with this one and make some IDM. Have fun!</p>
]]></content:encoded></item><item><title><![CDATA[WTF is "nextTick()"?]]></title><description><![CDATA[$nextTick is a somewhat mysterious property of Vue that is used for asynchronous DOM updates. It's a function that offers you some extra control over the standard reactive data flow. In order to understand this, let's define how Vue's reactivity work...]]></description><link>https://blog.kellenbaker.com/wtf-is-nexttick</link><guid isPermaLink="true">https://blog.kellenbaker.com/wtf-is-nexttick</guid><category><![CDATA[Vue.js]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Fri, 12 Nov 2021 21:31:18 GMT</pubDate><content:encoded><![CDATA[<p><code>$nextTick</code> is a somewhat mysterious property of Vue that is used for asynchronous DOM updates. It's a function that offers you some extra control over the standard reactive data flow. In order to understand this, let's define how Vue's reactivity works. </p>
<h2 id="vue-reactivity">Vue Reactivity</h2>
<p>Data is passed into a Vue component as a JavaScript object. Vue adds <code>getter</code> and <code>setter</code> functions to this object. Whenever this data changes, Vue will trigger either the <code>getter</code> function to collect this change as a dependency, or a <code>setter</code> function to notify the component that something has changed. </p>
<blockquote>
<p>"Every component instance has a corresponding watcher instance, which records any properties “touched” during the component’s render as dependencies. Later on when a dependency’s setter is triggered, it notifies the watcher, which in turn causes the component to re-render." - https://vuejs.org/v2/guide/reactivity.html</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636749497417/JjhFWbOgw.png" alt="image.png" /></p>
<p>You can learn more about this with this free lesson on <a target="_blank" href="https://www.vuemastery.com/courses/advanced-components/build-a-reactivity-system/">Vue Mastery</a>.</p>
<h2 id="where-does-dollarnexttick-fit-in-all-this">Where does <code>$nextTick()</code> fit in all this?</h2>
<p>Here is the definition of <code>nextTick</code> straight from the proverbial horse's mouth: </p>
<blockquote>
<p>Vue.nextTick( [callback, context] )
Arguments:
{Function} [callback]
{Object} [context]
Usage:
Defer the callback to be executed after the next DOM update cycle. Use it immediately after you’ve changed some data to wait for the DOM update.
-- https://vuejs.org/v2/api/#Vue-nextTick</p>
</blockquote>
<p>Say what? Let's break this down. </p>
<p><code>Vue.nextTick</code>: This indicates that <code>nextTick</code> is a property on the Vue instance.</p>
<p><code>( [callback, context] )</code>: The <code>callback</code> is the name of the function to execute on the next tick. The <code>context</code> is the detail inside the function's curly brackets that define what the function should do. </p>
<p><code>Defer the callback</code>: Wait to perform this function</p>
<p><code>to be executed after the next DOM update cycle</code>: Until the next DOM update cycle. (The DOM update cycle is the loop displayed in the image above.)</p>
<p><code>Use it immediately after you've changed some data to wait for the DOM update.</code>: <strong>This</strong> is the most important part of the concept of <code>nextTick</code>. Its usefulness lies in the fact that it can delay something until the DOM has re-rendered, ensuring that this callback function will run with the latest data. </p>
<p>Vue's reactivity system does a great job of keeping data updated, but <code>nextTick</code> is like a surgical scalpel that allows you to cut into the DOM update cycle and execute very granular control over it. It's not a tool you'll need every day, but it is a good thing to have on the table. If you ever get an error like <code>Uncaught (in promise) DOMException</code>, <code>nextTick</code> might be what you use to resolve it. Essentially, what <code>nextTick</code> says is: </p>
<p>"Wait until this current thing is done before executing this other thing."</p>
<p>Check out the resources below for code examples of how <code>nextTick</code> works.</p>
<p>Resources</p>
<ul>
<li>https://vuejsdevelopers.com/2019/01/22/vue-what-is-next-tick/</li>
<li>https://vuejs.org/v2/guide/reactivity.html</li>
<li>https://vuejs.org/v2/api/#Vue-nextTick</li>
<li>https://blog.logrocket.com/understanding-nexttick-in-vue-js/</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Reactive CSS Variables in a Vue Component]]></title><description><![CDATA[I recently created a page that embedded a huuuuuuuge table into a fixed viewport using some simple CSS: 
<template>
<div id="app">
      <div id="navbar"> NAVBAR </div>
      <div class="content-wrapper">
        <div id="header">HEADER</div>
       ...]]></description><link>https://blog.kellenbaker.com/reactive-css-variables-in-a-vue-component</link><guid isPermaLink="true">https://blog.kellenbaker.com/reactive-css-variables-in-a-vue-component</guid><category><![CDATA[Vue.js]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Mon, 08 Nov 2021 18:56:24 GMT</pubDate><content:encoded><![CDATA[<p>I recently created a page that embedded a huuuuuuuge table into a fixed viewport using some simple CSS: </p>
<pre><code><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"navbar"</span>&gt;</span> NAVBAR <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"content-wrapper"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"header"</span>&gt;</span>HEADER<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"table-wrapper"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"table"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">thead</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">th</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">"(col, i) in columns"</span> <span class="hljs-attr">:key</span>=<span class="hljs-string">"i"</span>&gt;</span>{{ col }}<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">thead</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">tbody</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">tr</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">"person, j in people"</span> <span class="hljs-attr">:key</span>=<span class="hljs-string">"j"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ person.namefirst}}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ person.namelast }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ person.email }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span> {{ person.username }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span> {{ person.age }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span> {{ person.country}}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span> {{ person.birthdate }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ person.creditcard }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{person.password}}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{person.phone}}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{person.sex}}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{person.ssn}}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{person.url}}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{person.maritalstatus}}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{person.county}}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{person.postcode}}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{person.state}}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{person.coordinates}}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{person.city}}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{person.address}}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">tbody</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">table</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>

...

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
<span class="hljs-selector-id">#app</span> {
  <span class="hljs-attribute">font-family</span>: Avenir, Helvetica, Arial, sans-serif;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">90vw</span>;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span> auto;
}

  <span class="hljs-selector-class">.table-wrapper</span> {
    <span class="hljs-attribute">position</span>: absolute;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">90vw</span>;
    <span class="hljs-attribute">overflow-x</span>: auto;
    <span class="hljs-attribute">overflow-y</span>: auto;
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre><p>This was simple enough, but I needed the horizontal scroll bar to always be pinned to the bottom of the viewport, no matter how large the table is. This presents a few problems that need to be solved in JavaScript. </p>
<p>First, we'll need to get the window height. This needs to be responsive in case the viewport size changes while the user is using the app. Setup an event listener in the <code>mounted()</code> function when the app loads: </p>
<pre><code><span class="hljs-keyword">async</span> mounted() {
    <span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">'resize'</span>, <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
      <span class="hljs-built_in">this</span>.windowHeight = <span class="hljs-built_in">window</span>.innerHeight
    })
</code></pre><p>We still need more information. In order to position the table directly below the header, we'll need to know more about the header's size. (In this app, the header size could also vary.) In order to do this, we will use a JavaScript method called <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect">getBoundingClientRect</a>. This returns an object that can tell us a lot about where an element is positioned on the page.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636394358838/t70YMsUH5.png" alt="image.png" /></p>
<p>The header properties will be calculated after the header appears on the DOM, using a computed value:</p>
<pre><code>computed: {
    headerPositionY() {
      <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>.isLoading) {
        <span class="hljs-keyword">return</span> document.getElementById(<span class="hljs-string">'header'</span>).getBoundingClientRect().y
      }
      <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
    },
    headerHeight() {
      <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>.isLoading) {
        <span class="hljs-keyword">return</span> document.getElementById(<span class="hljs-string">'header'</span>).getBoundingClientRect().height
      }
      <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
    },
},
</code></pre><p>Now we have enough information to calculate the table height. This is also placed in the <code>computed</code> values: </p>
<pre><code>tableHeight() {
      <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>.isLoading) {
        <span class="hljs-keyword">return</span> (
          Math.round(<span class="hljs-keyword">this</span>.windowHeight) -
          Math.round(<span class="hljs-keyword">this</span>.headerPositionY) -
          Math.round(<span class="hljs-keyword">this</span>.headerHeight) 
        )
      }
      <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
    },
</code></pre><p>Then, we can create another <code>computed</code> value to return the styles to apply to the table: </p>
<pre><code>tableStyles() {
      <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>.isLoading) {
        <span class="hljs-keyword">return</span> `height: ${<span class="hljs-keyword">this</span>.tableHeight}px;`
      }
      <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
    },
</code></pre><p>Apply these styles to the table wrapper: </p>
<pre><code>&lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"table-wrapper"</span> :style=<span class="hljs-string">"tableStyles"</span>&gt;
...
</code></pre><p>Check out the full example here:  https://codepen.io/mkbaker/pen/jOLZYwN</p>
<p>Additional resources:</p>
<p>https://stackoverflow.com/questions/1480133/how-can-i-get-an-objects-absolute-position-on-the-page-in-javascript/16626843#16626843</p>
<p>https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect</p>
<p>https://developer.mozilla.org/en-US/docs/Web/API/DOMRect</p>
<p>https://www.telerik.com/blogs/passing-variables-to-css-on-a-vue-component</p>
<p>https://stackoverflow.com/questions/65223560/what-unit-does-getboundingclientrect-return-in</p>
<p>https://stackoverflow.com/questions/49268659/javascript-get-100vh-in-pixels</p>
<p>https://stackoverflow.com/questions/50490561/computed-property-reactive-to-window-innerwidth-in-vuejs</p>
]]></content:encoded></item><item><title><![CDATA[Using localStorage with your Vue app]]></title><description><![CDATA[If you learned to code in the era of modern frontend JavaScript frameworks, you might be unfamiliar with localStorage and how to use it. After all, when developing Vue apps, it makes more sense to use Vuex to share data between all your components. B...]]></description><link>https://blog.kellenbaker.com/using-localstorage-with-your-vue-app</link><guid isPermaLink="true">https://blog.kellenbaker.com/using-localstorage-with-your-vue-app</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Vue.js]]></category><category><![CDATA[localstorage]]></category><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Mon, 18 Oct 2021 19:44:40 GMT</pubDate><content:encoded><![CDATA[<p>If you learned to code in the era of modern frontend JavaScript frameworks, you might be unfamiliar with <code>localStorage</code> and how to use it. After all, when developing Vue apps, it makes more sense to use Vuex to share data between all your components. But what if you have a standalone Vue app powering a single piece of a larger, non-Vue application? </p>
<p>Before we begin, <a target="_blank" href="https://www.w3schools.com/jsref/prop_win_localstorage.asp">here's a great explanation</a> of <code>localStorage</code> from W3Schools.</p>
<p>Let's say your app has a dashboard that's running Vue, but the rest of the application is built with templated HTML. The dashboard allows the user to select content from a list of tabs. Within each tab is a data table with a bunch of information that doesn't really matter to us -- all we need to remember is which tab the user selected. The user will follow whatever content is linked in the data tables, but when the user is returned to the dashboard, we want to return them to the same tab from which they exited the dashboard. Since the Vue app's data is cleared every time the user navigates away from the page, we cannot simply store this value for later.</p>
<p>Our <code>data</code> looks something like this: </p>
<pre><code><span class="hljs-selector-tag">data</span>() {
     <span class="hljs-selector-tag">return</span> {
          <span class="hljs-attribute">availableTabs</span>: [
                    { <span class="hljs-attribute">display_name</span>: <span class="hljs-string">'Draft'</span>, <span class="hljs-attribute">value</span>: <span class="hljs-number">10</span> },
                    { <span class="hljs-attribute">display_name</span>: <span class="hljs-string">'In Review'</span>, <span class="hljs-attribute">value</span>: <span class="hljs-number">11</span> }
                    { <span class="hljs-attribute">display_name</span>: <span class="hljs-string">'Edit Required'</span>, <span class="hljs-attribute">value</span>: <span class="hljs-number">12</span> },
                    { <span class="hljs-attribute">display_name</span>: <span class="hljs-string">'Published'</span>, <span class="hljs-attribute">value</span>: <span class="hljs-number">13</span> }
               ],
          <span class="hljs-attribute">selected</span>: {}
     }
}
</code></pre><p>The user can select from any of the <code>availableTabs</code>. We need to store the <code>selected</code> value for later. Let's setup a watcher to react whenever <code>selected</code> is updated: </p>
<pre><code>  <span class="hljs-selector-tag">watch</span>: {
    <span class="hljs-attribute">selected</span>: <span class="hljs-built_in">function</span>(newValue, oldValue) {
      localStorage.<span class="hljs-built_in">setItem</span>(<span class="hljs-string">'selected'</span>, JSON.stringify(newValue))
    }
}
</code></pre><p>This will save the <code>selected</code> object to the browser's <code>localStorage</code> every time it is updated by the user. When the user returns to the dashboard, we need to get the previously selected tab when the page is loading. Let's do this in our <code>mounted</code> function: </p>
<pre><code>mounted() {
      let previouslySelected = JSON.parse(localStorage.getItem(<span class="hljs-string">'selected'</span>))
      <span class="hljs-keyword">if</span> (previouslySelected) {
        <span class="hljs-keyword">if</span> (
          <span class="hljs-keyword">this</span>.availableTabs.find(x =&gt; x.value === previouslySelected.value)
        ) {
          <span class="hljs-keyword">return</span> (<span class="hljs-keyword">this</span>.selected = previouslySelected)
        } <span class="hljs-keyword">else</span> {
          <span class="hljs-keyword">return</span> (<span class="hljs-keyword">this</span>.selected = { display_name: <span class="hljs-string">'Draft'</span>, value: <span class="hljs-number">10</span>})
        }
      }
}
</code></pre><p>Great! Now this should load the previously selected tab when the user returns to the dashboard. </p>
<p>Lastly, it might be a good idea to delete the localStorage data when the user logs out. I accomplished this by attaching this small piece of vanilla JavaScript to the app's logout button: </p>
<pre><code><span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'logout-btn'</span>).onclick = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">window</span>.localStorage.clear()
}
</code></pre><p>Another option is to use <code>sessionStorage</code> instead, which will delete this information when the browser is closed. Here's a great tutorial on that: https://linguinecode.com/post/clear-localstorage-browser-tab-closing</p>
]]></content:encoded></item><item><title><![CDATA[typeof null]]></title><description><![CDATA[In JavaScript, typeof is a useful operator for parsing data. typeof returns a string that describes the data type of the value passed in.
Example:
typeof 1234 // "number"
typeof "abcd" // "string"
typeof false // "boolean"
typeof { foo: "bar" } // "o...]]></description><link>https://blog.kellenbaker.com/typeof-null</link><guid isPermaLink="true">https://blog.kellenbaker.com/typeof-null</guid><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Thu, 12 Aug 2021 15:59:13 GMT</pubDate><content:encoded><![CDATA[<p>In JavaScript, <code>typeof</code> is a useful operator for parsing data. <code>typeof</code> returns a string that describes the data type of the value passed in.</p>
<p>Example:</p>
<pre><code class="lang-ruby">typeof <span class="hljs-number">1234</span> /<span class="hljs-regexp">/ "number"
typeof "abcd" /</span><span class="hljs-regexp">/ "string"
typeof false /</span><span class="hljs-regexp">/ "boolean"
typeof { foo: "bar" } /</span><span class="hljs-regexp">/ "object"</span>
</code></pre>
<p>There are a few confusing cases in <code>typeof</code>. These are:</p>
<pre><code class="lang-ruby">typeof [a, b, c] /<span class="hljs-regexp">/ "object"
typeof NaN /</span><span class="hljs-regexp">/ "number"
typeof null /</span><span class="hljs-regexp">/ "object"</span>
</code></pre>
<p>Kind of weird, right? The <code>null</code> value being read as "object" is especially unexpected. According to https://bitsofco.de/javascript-typeof/, this is due to the way <code>null</code> is represented in computer memory.</p>
<p>In order to determine a value of <code>null</code>, you will need to also determine that the value is <code>!== null</code>. I had a use case where I was building a payload and needed to determine if the incoming data was an empty object or was truly null. If the data was an array, I needed to make sure that the value in the payload was an empty array. Likewise, I needed to ensure that <code>null</code> values were not assigned to be an empty array, but remained <code>null</code>.</p>
<pre><code class="lang-ruby"><span class="hljs-keyword">if</span> (typeof payload[key] === <span class="hljs-string">'object'</span> &amp;&amp; payload[key] !== null) {
            payload[key] = []
          } <span class="hljs-keyword">else</span> {
            payload[key] = null
          }
</code></pre>
<p>This <code>if</code> statement will check if a value is an object and ensure that the value is not <code>null</code> returning the <code>object</code> type.</p>
]]></content:encoded></item><item><title><![CDATA[Get data using current URL with JavaScript]]></title><description><![CDATA[You can get the URL object using window.location.href like this: 
let url = new URL(window.location.href)
Then, parse that URL with split to get the data you need:
let id = url.pathname.split('/')[2]
In this case, the URL I got was http://127.0.0.1:8...]]></description><link>https://blog.kellenbaker.com/get-data-using-current-url-with-javascript</link><guid isPermaLink="true">https://blog.kellenbaker.com/get-data-using-current-url-with-javascript</guid><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Thu, 05 Aug 2021 21:27:53 GMT</pubDate><content:encoded><![CDATA[<p>You can get the URL object using <code>window.location.href</code> like this: </p>
<pre><code>let url = <span class="hljs-built_in">new</span> URL(<span class="hljs-keyword">window</span>.<span class="hljs-keyword">location</span>.href)
</code></pre><p>Then, parse that URL with <code>split</code> to get the data you need:</p>
<pre><code><span class="hljs-built_in">let</span> id = url.pathname.split(<span class="hljs-string">'/'</span>)[2]
</code></pre><p>In this case, the URL I got was <code>http://127.0.0.1:8000/request/1/update/</code>. The <code>pathname</code> is equal to <code>/request/1/update/</code>. The <code>1</code> is the ID of the data object I need. </p>
<p>Once you've got the ID, you can use it in an axios call to get the data you need. </p>
]]></content:encoded></item><item><title><![CDATA[Add mermaid-js to mkdocs]]></title><description><![CDATA[If you're using mkdocs, you may be interested in creating visual diagrams with  mermaid. 
Adding mermaid to your mkdocs project is fairly easy.  First, install mkdocs-mermaid2-plugin using pip install mkdocs-mermaid2-plugin. 
Add the following to mkd...]]></description><link>https://blog.kellenbaker.com/add-mermaid-js-to-mkdocs</link><guid isPermaLink="true">https://blog.kellenbaker.com/add-mermaid-js-to-mkdocs</guid><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Wed, 21 Apr 2021 21:20:31 GMT</pubDate><content:encoded><![CDATA[<p>If you're using mkdocs, you may be interested in creating visual diagrams with  <a target="_blank" href="https://mermaid-js.github.io/mermaid/#/README">mermaid</a>. </p>
<p>Adding mermaid to your mkdocs project is fairly easy.  First, install <a target="_blank" href="https://pypi.org/project/mkdocs-mermaid2-plugin/">mkdocs-mermaid2-plugin</a> using <code>pip install mkdocs-mermaid2-plugin</code>. </p>
<p>Add the following to <code>mkdocs.yml</code>:</p>
<pre><code>plugins:
<span class="hljs-bullet">    -</span> search
<span class="hljs-bullet">    -</span> mermaid2
</code></pre><p>('search' should already exist here)</p>
<p>Add this to the <code>mkdocs.yml</code> file as well:</p>
<pre><code><span class="hljs-attribute">extra_javascript</span>:
    - <span class="hljs-attribute">https</span>:<span class="hljs-comment">//unpkg.com/mermaid/dist/mermaid.min.js</span>
</code></pre><p>And that's it!</p>
]]></content:encoded></item><item><title><![CDATA[In Defense of "Dumbing it Down"]]></title><description><![CDATA[I don't know about you, but I feel like the pandemic has pushed my undiagnosed ADHD into overdrive. I constantly have to reel myself in from an ever expanding thought cloud. Sitting through Zoom calls feels like torture. Reading documentation is tedi...]]></description><link>https://blog.kellenbaker.com/in-defense-of-dumbing-it-down</link><guid isPermaLink="true">https://blog.kellenbaker.com/in-defense-of-dumbing-it-down</guid><category><![CDATA[communication]]></category><category><![CDATA[teaching]]></category><category><![CDATA[team]]></category><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Wed, 07 Apr 2021 15:17:02 GMT</pubDate><content:encoded><![CDATA[<p>I don't know about you, but I feel like the pandemic has pushed my undiagnosed ADHD into overdrive. I constantly have to reel myself in from an ever expanding thought cloud. Sitting through Zoom calls feels like torture. Reading documentation is tedious and inefficient, and I can often forget what I'm looking for in the first place. Keeping up with coworkers in this day and age is another struggle, since they're reduced to text and an avatar in my Teams or Slack channel. And if it's not in writing? It might as well not exist. </p>
<p>The solution to this is to "dumb it down." Technology needs to work for our anxiety-riddled monkey brains, and humans need to remember that it's here to serve us -- not the other way around. Reaching into my background in elementary education, I can see three areas where "dumbing it down" would work great for adults, too:</p>
<ol>
<li>Go in with a plan.</li>
<li>Keep it direct and clear.</li>
<li>Monotask everything.</li>
</ol>
<h1 id="go-in-with-a-plan">Go in with a plan</h1>
<p>Every meeting should have a reason. You should be able to express this reason in writing at the time of inviting. Before you send out a meeting invitation, write an outline of what will happen in the meeting -- the who, what, when, where, and why.</p>
<ul>
<li>Who: Provide a list of invitees in the meeting invitation. Keeping this info in the text of the calendar invite is helpful, as not all calendar software allows you to view the attendees.</li>
<li>Why: Identify the desired outcome of this meeting. Are we brainstorming new solutions? Are we swarming on a specific problem? What are we going to accomplish in this time? </li>
<li>When: Duh.</li>
<li>Where: Also duh. </li>
<li>What: This is where you can provide an outline. This can include planned activities, or even time slots when you expect those activities to happen. It can be as simple as:</li>
</ul>
<blockquote>
<p>1:00-1:15: Introductions </p>
<p>1:15-1:30: Presentation on topic</p>
<p>1:30-2:00: Discussion</p>
</blockquote>
<p>You should also make plans for yourself. This can be as simple as writing down your questions before your stand-up meeting, or as in-depth as creating an entire lesson plan for a lunch-and-learn. Nobody needs to see your personal plans, but make sure they're clear and understandable -- future you will be grateful. </p>
<p>Remember in high school when they told you not to just "read off the slides" when giving a PowerPoint presentation? I am urging everyone to disregard this advice. It's impossible to read something and listen to someone speaking at the same time. You can always expand on your bullet points, but please read the bullet point first. This helps the audience follow along. Most people are visual learners, so use the presentation slides to your advantage to get your point across clearly.</p>
<h1 id="keep-it-direct-and-clear">Keep it direct and clear</h1>
<p>This goes for any kind of communication. Cut out all unnecessary words, especially if writing documentation. Try to explain things in the simplest possible terms, as if explaining to a kid. (This is a tricky balance -- explain things so a child could understand, but not like you're talking to a child.) If the concept you're explaining requires background knowledge, provide links so the reader can learn more. Keeping to a single topic will shorten your documents and make it easier for the reader to find what they're looking for. </p>
<p>When speaking, slow down your pace and choose your words carefully. Check in with listeners to make sure you're being understood.</p>
<h1 id="monotask-everything">Monotask Everything</h1>
<blockquote>
<p>"When you do something, you should burn yourself up completely, like a good bonfire, leaving no trace of yourself."
– Shunryu Suzuki</p>
</blockquote>
<p>Ok, maybe 'burn yourself up' is bad work advice, but the sentiment is this: When you are completely absorbed by what you're working on, you are doing your best work. 
The secret to getting in this zone is monotasking. </p>
<p>Monotasking means only doing one thing at a time. When you're in a meeting, be IN the meeting -- not chatting with a friend, not working on something else. When you're coding, block out distractions like email or Slack so you won't be interrupted. Put your phone on silent, or better yet in another room. </p>
<p>I'll admit this is the hardest part for me. There's so much to do and so little time, how can I NOT multitask? It's important to remember that when you're monotasking, your work will be higher quality, and this will save you time in the long run. Long term benefits &gt; short term benefits.</p>
<p>How has the pandemic affected the way you work? What are you doing to address those issues in your company? Let me know in the comments.</p>
]]></content:encoded></item><item><title><![CDATA[Find a Bearer Token in Chrome]]></title><description><![CDATA[Occasionally, you'll need to update your bearer token when using Postman to test APIs. Below, I'll describe how to find the token in your local application. This is one of those tasks that seems to happen frequently enough that I should know how to d...]]></description><link>https://blog.kellenbaker.com/find-a-bearer-token-in-chrome</link><guid isPermaLink="true">https://blog.kellenbaker.com/find-a-bearer-token-in-chrome</guid><category><![CDATA[Auth0]]></category><category><![CDATA[JWT]]></category><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Tue, 09 Feb 2021 21:12:12 GMT</pubDate><content:encoded><![CDATA[<p>Occasionally, you'll need to update your bearer token when using Postman to test APIs. Below, I'll describe how to find the token in your local application. This is one of those tasks that seems to happen frequently enough that I should know how to do it, but infrequently enough that I can never remember. Here's a reminder for future me (and maybe current you!):</p>
<p>First make sure your console is open to the network tab so that you will have access to this info: 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1612904912801/nqDWDcodF.png" alt="image.png" /></p>
<p>Locate the response from the /login call: 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1612905049282/dZTJ_ryDy.png" alt="image.png" /></p>
<p>And BOOM -- there it is in the response tab: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1612905078428/x8DTmC4Yp.png" alt="image.png" /></p>
<p>Hopefully this saves future me an hour of research the next time this happens. :) </p>
]]></content:encoded></item><item><title><![CDATA[Connect to a MongoDB container with kubectl]]></title><description><![CDATA[Goal: Connect your local computer to a Mongo database running in a kubernetes cluster. 
Use case: Use a hosted database for local development. I have used this workflow to connect to databases hosted in Rancher, a container orchestrating service.
You...]]></description><link>https://blog.kellenbaker.com/connect-to-a-mongodb-container-with-kubectl</link><guid isPermaLink="true">https://blog.kellenbaker.com/connect-to-a-mongodb-container-with-kubectl</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[MongoDB]]></category><dc:creator><![CDATA[Kellen]]></dc:creator><pubDate>Fri, 29 Jan 2021 15:49:46 GMT</pubDate><content:encoded><![CDATA[<p>Goal: Connect your local computer to a Mongo database running in a kubernetes cluster. </p>
<p>Use case: Use a hosted database for local development. I have used this workflow to connect to databases hosted in Rancher, a container orchestrating service.</p>
<p>You need to know: </p>
<ul>
<li>kubernetes namespace</li>
<li>pod name</li>
</ul>
<p>The command looks like this: 
<code>kubectl -n namespace port-forward podName 31137:27017</code></p>
<p>Where namespace is the kubernetes namespace and podName is the name of the pod.
Example:
<code>kubectl -n namepsace-to-connect-to port-forward name-of-pod-12345-4321 31137:27017</code></p>
<p>Running this command in your terminal will open up a port connection on 31137, which you can then use to connect to the Mongo database with a GUI such as MongoDB Compass. Be sure to keep the terminal open to run in the background!</p>
]]></content:encoded></item></channel></rss>