<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://wrightperspective.net/feed.xml" rel="self" type="application/atom+xml" /><link href="https://wrightperspective.net/" rel="alternate" type="text/html" /><updated>2025-03-31T10:31:01+00:00</updated><id>https://wrightperspective.net/feed.xml</id><title type="html">the Wright Perspective</title><subtitle>Random ill-formed thoughts from Scott Wright.</subtitle><entry><title type="html">Configuring Pry</title><link href="https://wrightperspective.net/2022/04/configuring-pry" rel="alternate" type="text/html" title="Configuring Pry" /><published>2022-04-14T10:26:54+00:00</published><updated>2022-04-14T10:26:54+00:00</updated><id>https://wrightperspective.net/2022/04/configuring-pry</id><content type="html" xml:base="https://wrightperspective.net/2022/04/configuring-pry"><![CDATA[<h1 id="configuring-pry">Configuring Pry</h1>

<p>I use Pry as my REPL for all my Ruby projects. In fact, Pry is one of the reasons Ruby has “stuck” with me. I find
the commands both intuitive and helpful. I have a text expansion that I constantly use in development:
;pry -&gt; binding.pry if !@jsw_skip_pry
The if clause is there to allow easy exits from loops - once I see what I need to see, I set the instance variable
to true to avoid all subsequent breaks.</p>

<p>I have been using Pry for years and I have never messed with its configuration. Just this week I was debugging a
pretty involved class. The instantiated class often has A LOT of instance variables (maybe that’s a code smell?
That’s a topic for another day which may never come). I was getting an exception in this instantiated class unrelated
to the instance variables. Pry’s default exception handler, which is one of the reason’s I love Pry, in this case was
spitting out all of the instance variables which was taking up literally hundreds of lines in my terminal and I was
having to scroll through all of these lines to see the actual exception that was being thrown. It got to be too much. I
went in search of options to tame the exception output. Pry did not disapoint. I found a <a href="https://github.com/pry/pry/wiki/Customization-and-configuration#Config_exception">great resource for configuring
Pry’s exception handler</a>. Lot’s of
options there. The big takeaways for me were that it’s fairly trivial to override its default handler and that you can
do it in either the active session, or in a .pryrc file<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>.</p>

<p>Here is my Pry exception handler from my .pryrc in my home directory:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">Pry</span><span class="p">.</span><span class="nf">config</span><span class="p">.</span><span class="nf">exception_handler</span> <span class="o">=</span> <span class="nb">proc</span> <span class="k">do</span> <span class="o">|</span><span class="n">output</span><span class="p">,</span> <span class="n">exception</span><span class="p">,</span> <span class="n">_</span><span class="o">|</span>
  <span class="n">output</span><span class="p">.</span><span class="nf">puts</span> <span class="s2">"</span><span class="si">#{</span><span class="n">exception</span><span class="p">.</span><span class="nf">class</span><span class="p">.</span><span class="nf">name</span><span class="si">}</span><span class="s2">: </span><span class="si">#{</span><span class="n">exception</span><span class="p">.</span><span class="nf">message</span><span class="si">}</span><span class="se">\n</span><span class="s2">"</span>
  <span class="n">exception</span><span class="p">.</span><span class="nf">backtrace</span><span class="p">.</span><span class="nf">each</span> <span class="p">{</span><span class="o">|</span><span class="n">ebt</span><span class="o">|</span> <span class="n">output</span><span class="p">.</span><span class="nf">puts</span> <span class="n">ebt</span> <span class="k">if</span> <span class="n">ebt</span><span class="p">.</span><span class="nf">match?</span><span class="p">(</span><span class="sr">/^(?!.*(__pry__|\/gems\/|&lt;main&gt;)).*$/</span><span class="p">)}</span>
<span class="k">end</span>
</code></pre></div></div>
<p>This handler omits the default handler’s object inspection, which is what causes all the instance variables to be
displayed. I am also filtering the backtrace to exclude any lines referencing, pry, gems, and main because 99% of the
time I am only interested in errors from my code and this dramtically reduces the backtrace. If I ever need the more
verbose default exception, I can always comment out my code in my ~/.pryrc and start a new session, or, better yet,
create a different handler in my current Pry session:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">pry_instance</span><span class="p">.</span><span class="nf">config</span><span class="p">.</span><span class="nf">exception_handler</span> <span class="o">=</span> <span class="nb">proc</span> <span class="k">do</span> <span class="o">|</span><span class="n">output</span><span class="p">,</span> <span class="n">exception</span><span class="p">,</span> <span class="n">_</span><span class="o">|</span>
  <span class="n">output</span><span class="p">.</span><span class="nf">puts</span> <span class="s2">"</span><span class="si">#{</span><span class="n">exception</span><span class="p">.</span><span class="nf">class</span><span class="si">}</span><span class="s2">: </span><span class="si">#{</span><span class="n">exception</span><span class="p">.</span><span class="nf">message</span><span class="si">}</span><span class="s2">"</span>
  <span class="n">output</span><span class="p">.</span><span class="nf">puts</span> <span class="s2">"from </span><span class="si">#{</span><span class="n">exception</span><span class="p">.</span><span class="nf">backtrace</span><span class="p">.</span><span class="nf">first</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>
</code></pre></div></div>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>.pryrc files follow a common configuration convention in that your directory tree is searched from root to your current directory for .pryrc files and options are loaded from any found. Settings from earlier .pryrcs found closer to your working directory override the earlier setting. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name></name></author><category term="ruby" /><category term="terminal" /><summary type="html"><![CDATA[Configuring Pry]]></summary></entry><entry><title type="html">SSH Tunnel</title><link href="https://wrightperspective.net/2022/04/ssh-tunnel" rel="alternate" type="text/html" title="SSH Tunnel" /><published>2022-04-01T11:01:49+00:00</published><updated>2022-04-01T11:01:49+00:00</updated><id>https://wrightperspective.net/2022/04/ssh-tunnel</id><content type="html" xml:base="https://wrightperspective.net/2022/04/ssh-tunnel"><![CDATA[<h2 id="tldr">tldr</h2>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>ssh <span class="nt">-L</span> 6380:localhost:6379 secure-remote-server.example.com <span class="nt">-N</span> &amp;
</code></pre></div></div>
<p>6380: port where I can access the service on my local machine localhost:6380<br />
6379: port that the server runs on on the remote machine<br />
-L: local socket:host:port does the heavy lifting creating the and exposing the tunnel<br />
-N: does not execute a command on the remote machine<br />
&amp;: runs this command in the background<br /></p>

<p>Every time I need to do this, I have to search the web for instructions. Every time I search the web for instructions
I end up slogging through a bunch of results that either don’t make sense to me, or are just different enough from what
I am trying to do that I can’t accomplish my goal.</p>

<p>What I am almost always trying to do is expose a service running on some port on my server. My server is configured, for
security reasons, to open as few ports as necessary to outside requests. This means I open 80 &amp; 443 for web traffic, and
22 for SSH and almost nothing else. I do not open ports for the database, or for Redis, or just about any other service
but I occasionally have a need to access these services from a remote machine. SSH Tunnel to the rescue!</p>

<p>An SHH tunnel creates a secure tunnel from one machine to another using SSH and it allows me to run a command on my local
machine to access a port (via the tunnel) on the remote machine that is not otherwise open to remote requests. So if I
want to view data from Redis on secure-remote-server.example.com on my local machine, and the remote server is running
Redis and serving it to it’s localhost on port 6379 (localhost:6379), I would do the following on my local machine</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>ssh <span class="nt">-L</span> 6380:localhost:6379 secure-remote-server.example.com <span class="nt">-N</span> &amp;
</code></pre></div></div>

<p>The above command assumes my username on the remote machine is the same as my username on my local machine. If not, I
prepend the username plus @ in front of the remote server.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>ssh <span class="nt">-L</span> 6380:localhost:6379 user@secure-remote-server.example.com <span class="nt">-N</span> &amp;
</code></pre></div></div>]]></content><author><name></name></author><category term="cli" /><category term="terminal" /><category term="ssh" /><summary type="html"><![CDATA[tldr $ ssh -L 6380:localhost:6379 secure-remote-server.example.com -N &amp; 6380: port where I can access the service on my local machine localhost:6380 6379: port that the server runs on on the remote machine -L: local socket:host:port does the heavy lifting creating the and exposing the tunnel -N: does not execute a command on the remote machine &amp;: runs this command in the background]]></summary></entry><entry><title type="html">WordleQuarant on Twitter</title><link href="https://wrightperspective.net/2022/01/wordlequarant-on-twitter" rel="alternate" type="text/html" title="WordleQuarant on Twitter" /><published>2022-01-14T14:58:05+00:00</published><updated>2022-01-14T14:58:05+00:00</updated><id>https://wrightperspective.net/2022/01/wordlequarant-on-twitter</id><content type="html" xml:base="https://wrightperspective.net/2022/01/wordlequarant-on-twitter"><![CDATA[<p><a href="https://twitter.com/wordlequarant">@WordleQuarant</a> is a Twitter account created by <a href="https://twitter.com/backlon">Dieter Bohn</a>
to do 1 simple thing: Allow people to post their <a href="https://www.powerlanguage.co.uk/wordle/">Wordle</a> results to their
followers, but <strong>only</strong> followers who have self selected as interested in Wordle results.</p>

<p>How do they self select? They self select by following <a href="https://twitter.com/wordlequarant">@WordleQuarant</a> on Twitter.</p>

<p>How does one make sure only these
self selected followers see their Wordle results? Start a new Tweet with the very first characters “@WordleQuarant “,
no dots or spaces before the @, the space after coulld be a return or just a space, and then paste the copied Worsle results. Here is a recent example:</p>

<p><a href="https://twitter.com/jswright61/status/1481938097717882881"><img src="/assets/images/wordle_tweet.png" alt="Wordle Post example" /></a></p>

<p>Why does this work? It goes back to the early days of Twitter. Tweets that start with an @mention, by default, are seen
only by the mentioned party and those that follow both the author and the mentioned party. The tweets are public and
visible in the author’s list of Tweets and in the mentioned party’s mentions, but others will not see them in their
own default timeline unless they follow both accounts. This is why you see so many Tweets that begin with a period
followed by an @mention (.@jswright61). This is an early convention whereby someone could direct a Tweet at a specific
account and making it default visible to all of the author’s followers as well.</p>]]></content><author><name></name></author><category term="twitter" /><category term="games" /><category term="word_games" /><summary type="html"><![CDATA[@WordleQuarant is a Twitter account created by Dieter Bohn to do 1 simple thing: Allow people to post their Wordle results to their followers, but only followers who have self selected as interested in Wordle results.]]></summary></entry><entry><title type="html">Hello World!</title><link href="https://wrightperspective.net/2022/01/hello-world" rel="alternate" type="text/html" title="Hello World!" /><published>2022-01-13T13:44:58+00:00</published><updated>2022-01-13T13:44:58+00:00</updated><id>https://wrightperspective.net/2022/01/hello-world</id><content type="html" xml:base="https://wrightperspective.net/2022/01/hello-world"><![CDATA[<h1 id="hello-from-the-wright-perspective">Hello from the Wright Perspective</h1>

<p>This is yet another attempt, after all previous attempts have failed, to carve out a place on the web for my thoughts
and ramblings.</p>

<p>For those interested it’s hosted on Github pages using the standard Jekyll theme, minima.</p>]]></content><author><name></name></author><category term="blog_meta" /><summary type="html"><![CDATA[Hello from the Wright Perspective]]></summary></entry><entry><title type="html">Thunder Road</title><link href="https://wrightperspective.net/2020/03/thunder-road" rel="alternate" type="text/html" title="Thunder Road" /><published>2020-03-30T18:00:00+00:00</published><updated>2020-03-30T18:00:00+00:00</updated><id>https://wrightperspective.net/2020/03/thunder-road</id><content type="html" xml:base="https://wrightperspective.net/2020/03/thunder-road"><![CDATA[<p><a href="http://www.youtube.com/watch?v=9KPMkKOWgVs"><img src="http://img.youtube.com/vi/9KPMkKOWgVs/0.jpg" alt="Youtube video" /></a></p>

<p>I learned about Laura on Twitter. Due to the Covid-19 pandemic she had both time and a need for some extra $ as she found herself unemployed. She decided to take requests to perform songs on piano and viola. She gratefully accepts donations. You can make a request and see how to donate if you want here. I made a request for Thunder Road and was thrilled with the rendition she and her accompanist performed.</p>]]></content><author><name></name></author><category term="media" /><category term="music" /><category term="bruce" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">It’s the Little Things</title><link href="https://wrightperspective.net/2017/06/its-the-little-things" rel="alternate" type="text/html" title="It’s the Little Things" /><published>2017-06-02T15:17:00+00:00</published><updated>2017-06-02T15:17:00+00:00</updated><id>https://wrightperspective.net/2017/06/its-the-little-things</id><content type="html" xml:base="https://wrightperspective.net/2017/06/its-the-little-things"><![CDATA[<p>One of the reasons I use Apple products is that they get the little things right. Even the seemingly little things that take a lot of work behind the scenes. Apple is especially good at anticipating helpful conveniences and, when I need them, they’re there. Take the tapbacks in Messages - these are the little bubbles that can be added in messages to like, question, lol at, etc. a previous message in the thread. Great stuff, cleans up the timeline in busy group messages. Well done Apple. But wait, who liked my message? Who gave it a thumbs down? Not only do I get a realtime message when someone interacts with a previous message (it’s a notification and not part of the timeline), but when scrolling back through a timeline I can long press on the tapback bubble and see all the tapbacks for that text at the top of my screen, and at the top of the screen I can tap on the particular icon, HaHa, for example, and see the contact image for everyone who laughed at that text. All the bases were covered.</p>

<p>When Apple fails to take care of the little things, I get a little disappointed. Opportunity lost. I get it. There is a finite amount of time and every feature cannot make it into the final product. Even if it’s just a few lines of code to implement a feature it takes time and resources (way more than a developer typing a few lines into Xcode).</p>

<p>Nicknames. There, I said it. Apple could make iOS way better in a lot of areas by implementing nicknames. Two quick wins off the top of my head: WiFi networks and Bluetooth devices. Manufacturers usually do a good job of naming things, but not always, and even when they do, sometimes there’s still a good reason for nicknames, if I want to differentiate between two identical devices, for instance. But when the manufacturer swings and misses and names their device something generic, nicknames would be especially useful.</p>

<p>The image below shows my current Bluetooth devices. Some names are better than other. MY-CAR works for me, but my wife has the same MY-CAR in her Bluetooth devices and it’s not hers.</p>

<p><img src="https://wrightperspective.net/assets/images/bluetooth_1.png" alt="Bluetooth devices screenshot" /></p>

<p>When I tap the i next to the first item above (Bluetooth - HORRIBLE name) I get the following screen. What if there was a nickname text box that allowed me to give this device a meaningful name (Porch Speakers in this case) and when saved, the above list would then display the nickname I just gave it instead of the stupid name the manufacturer used.</p>

<p><img src="https://wrightperspective.net/assets/images/bluetooth_2.jpeg" alt="Bluetooth device detail image" /></p>

<p>WiFi too. And especially here. How many 2Wrire, Linksys, or Netgear WiFi networks do you see? Maybe the device owner has no idea how to change the SSID, or maybe they don’t want to call attention to their network. Maybe you know the SSID and password for your neighbors WiFi - maybe they’re on AT&amp;T and you’re on Comcast and you’ve shared credentials for when one network is down. Wouldn’t it be nice to have the network show up as “William’s WiFi” instead of 2WIRE7843?</p>

<p>It’s the little things. This feature, if implemented, would go unnoticed by an overwhelming majority of iOS users, but those that notice would have yet another datapoint on how Apple gets the little things right.</p>]]></content><author><name></name></author><category term="apple" /><category term="ios" /><category term="ui" /><summary type="html"><![CDATA[One of the reasons I use Apple products is that they get the little things right. Even the seemingly little things that take a lot of work behind the scenes. Apple is especially good at anticipating helpful conveniences and, when I need them, they’re there. Take the tapbacks in Messages - these are the little bubbles that can be added in messages to like, question, lol at, etc. a previous message in the thread. Great stuff, cleans up the timeline in busy group messages. Well done Apple. But wait, who liked my message? Who gave it a thumbs down? Not only do I get a realtime message when someone interacts with a previous message (it’s a notification and not part of the timeline), but when scrolling back through a timeline I can long press on the tapback bubble and see all the tapbacks for that text at the top of my screen, and at the top of the screen I can tap on the particular icon, HaHa, for example, and see the contact image for everyone who laughed at that text. All the bases were covered.]]></summary></entry></feed>