Jekyll2018-09-01T16:41:23+00:00/chemturionAaron Kelton's thoughts from Dallas, TX.
Rails Active Support Array Extract!2018-09-01T13:15:00+00:002018-09-01T13:15:00+00:00/ruby/rails/array/2018/09/01/array-extract<p>A couple weeks ago I got my standard <a href="https://rails-weekly.ongoodbits.com/2018/08/18/cookies-with-purpose-array-extract-and-more">This Week in Rails</a> newsletter, and saw that someone had <a href="https://github.com/rails/rails/pull/33137">added the <code class="highlighter-rouge">extract!</code> “Extract Bang” method</a> to the Array class in Rails (Active Support):</p>
<blockquote>
<p>The method removes and returns the elements for which the block returns a true value.</p>
</blockquote>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">numbers</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">]</span>
<span class="n">odd_numbers</span> <span class="o">=</span> <span class="n">numbers</span><span class="p">.</span><span class="nf">extract!</span><span class="p">(</span><span class="o">&</span><span class="ss">:odd?</span><span class="p">)</span> <span class="c1"># => [1, 3]</span>
<span class="n">numbers</span> <span class="c1"># => [2, 4]</span></code></pre></figure>
<p>Arrays are my favorite, so I dove in a bit and learned more than I bargained for.</p>
<hr />
<h3 id="extending-rubys-array-class-in-active-support">Extending Ruby’s Array Class in Active Support</h3>
<p>First off, I was reminded that we can add our own methods to Ruby’s core classes, and I saw the convention that Rails uses to incorporate these additions. If you write your <code class="highlighter-rouge">extract!</code> code located like so:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>active_support/core_ext/array/extract.rb
</code></pre></div></div>
<p>then you must <code class="highlighter-rouge">require</code> it in a file located like so:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>active_support/core_ext/array.rb
</code></pre></div></div>
<p>where <code class="highlighter-rouge">array.rb</code> has lines looking something like:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">require</span> <span class="s2">"active_support/core_ext/array/extract"</span></code></pre></figure>
<p>So you’ve got all these custom method files extending the core Array class, and one file that requires them all. I learned that these extensions, when added, should have supporting tests (I also learned that Rails doesn’t use RSpec for testing!), located at</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rails/activesupport/test/core_ext/array/extract_test.rb
</code></pre></div></div>
<p>I’d like to go deeper, but this overview is a good start to understanding the Rails framework better. Read more about <a href="https://guides.rubyonrails.org/active_support_core_extensions.html">Active Support Core Extensions</a>.</p>
<hr />
<h3 id="array-elements-can-already-be-extracted-though">Array Elements Can Already Be Extracted Though!</h3>
<p>Ruby’s Enumerable module has had the <code class="highlighter-rouge">#partition</code> method going all the way back to <a href="https://ruby-doc.org/core-1.8.6/Enumerable.html#method-i-partition">Ruby version 1.8.6</a> (at least… I’m not sure how to go back further than that!). <code class="highlighter-rouge">#partition</code> returns two arrays based on an expression that returns <code class="highlighter-rouge">true</code> (first element), or <code class="highlighter-rouge">false</code> (second element):</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">].</span><span class="nf">partition</span> <span class="p">{</span> <span class="o">|</span><span class="n">v</span><span class="o">|</span> <span class="n">v</span><span class="p">.</span><span class="nf">even?</span> <span class="p">}</span> <span class="c1">#=> [[2, 4, 6], [1, 3, 5]]</span></code></pre></figure>
<p>If you want to assign these values, you gotta do that dual variable assignment bit:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">evens</span><span class="p">,</span> <span class="n">odds</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">].</span><span class="nf">partition</span> <span class="p">{</span> <span class="o">|</span><span class="n">v</span><span class="o">|</span> <span class="n">v</span><span class="p">.</span><span class="nf">even?</span> <span class="p">}</span>
<span class="n">evens</span> <span class="c1">#=> [2, 4, 6]</span>
<span class="n">odds</span> <span class="c1">#=> [1, 3, 5]</span></code></pre></figure>
<blockquote>
<p>For any beginners, remember that the <a href="https://ruby-doc.org/core-2.5.1/Array.html#includes-section">Array class includes the Enumerable module</a>, so it can use the <code class="highlighter-rouge">#partition</code> method.</p>
</blockquote>
<p>The problem with this approach is that it’s cumbersome. We want to extract elements, not partition-then-assign them! And later we’ll show how <a href="https://github.com/bogdanvlviv">Bogdan</a> ensured his <code class="highlighter-rouge">Array#extract!</code> method was better than the <code class="highlighter-rouge">Enumerable#partition</code> method.</p>
<h3 id="how-to-extract">How to Extract!</h3>
<p>Here’s <a href="https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/array/extract.rb">the method</a> in all its 6-line glory:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">def</span> <span class="nf">extract!</span>
<span class="k">return</span> <span class="n">to_enum</span><span class="p">(</span><span class="ss">:extract!</span><span class="p">)</span> <span class="p">{</span> <span class="n">size</span> <span class="p">}</span> <span class="k">unless</span> <span class="nb">block_given?</span>
<span class="n">extracted_elements</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">reject!</span> <span class="k">do</span> <span class="o">|</span><span class="n">element</span><span class="o">|</span>
<span class="n">extracted_elements</span> <span class="o"><<</span> <span class="n">element</span> <span class="k">if</span> <span class="k">yield</span><span class="p">(</span><span class="n">element</span><span class="p">)</span>
<span class="k">end</span>
<span class="n">extracted_elements</span>
<span class="k">end</span></code></pre></figure>
<p>The first line <code class="highlighter-rouge">return to_enum...</code> ensures that other methods can be chained thereon. I get the idea, but I’m not sure when you’d call <code class="highlighter-rouge">[1,2,3].extract!.<another_method></code>, so I’d need a concrete example to make it stick. I also don’t know why <code class="highlighter-rouge">{ size }</code> is used. Need to be walked thru that one. Just think of the first line as the tooth pick that holds together the sandwich.</p>
<p><img src="/assets/toothpick_sandwich.jpg" alt="Toothpick Sandwich" /></p>
<p>The <code class="highlighter-rouge">extracted_elements</code> variable is the bread of our method sandwich. It starts as an empty array, and then returns its new self after extraction is complete.</p>
<p>Let’s look at the meat of our method sandwich:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">reject!</span> <span class="k">do</span> <span class="o">|</span><span class="n">element</span><span class="o">|</span>
<span class="n">extracted_elements</span> <span class="o"><<</span> <span class="n">element</span> <span class="k">if</span> <span class="k">yield</span><span class="p">(</span><span class="n">element</span><span class="p">)</span>
<span class="k">end</span></code></pre></figure>
<p>When I first looked at this, I thought, “Does the <code class="highlighter-rouge">#reject!</code> method interact with my array, or each element from the block?” The syntactic sugar got a bit sweet, so here’s that first line in all its salty glory:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">self</span><span class="p">.</span><span class="nf">reject!</span> <span class="k">do</span> <span class="o">|</span><span class="n">element</span><span class="o">|</span></code></pre></figure>
<p>SELF! <code class="highlighter-rouge">self</code> in this case is our array. So if we have <code class="highlighter-rouge">[1,2,3,4,5,6].extract!{|n|n.even?}</code>, then <code class="highlighter-rouge">self</code> would be <code class="highlighter-rouge">[1,2,3,4,5,6]</code>.</p>
<p>I know how to shovel (<code class="highlighter-rouge"><<</code>) elements into an array, but I was a bit confused about the <code class="highlighter-rouge">yield(element)</code> bit. This is where our block comes into play. Imagine if we had a method called <code class="highlighter-rouge">#extract_even_numbers!</code>, it might look something like this:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">def</span> <span class="nf">extract_even_numbers!</span>
<span class="n">even_numbers</span> <span class="o">=</span> <span class="p">[]</span>
<span class="nb">self</span><span class="p">.</span><span class="nf">reject!</span> <span class="k">do</span> <span class="o">|</span><span class="n">element</span><span class="o">|</span>
<span class="n">even_numbers</span> <span class="o"><<</span> <span class="n">element</span> <span class="k">if</span> <span class="n">element</span><span class="p">.</span><span class="nf">even?</span>
<span class="k">end</span>
<span class="n">even_numbers</span>
<span class="k">end</span></code></pre></figure>
<p>This very specific extraction method for getting even numbers from an array depends on the <code class="highlighter-rouge">element.even?</code> part. OK, now put yourself back into the frame of mind for the <code class="highlighter-rouge">#extract!</code> method. The <code class="highlighter-rouge">yield(element)</code> bit (I almost used the forbidden “simply” term!) looks at the imposing block, holds the door open, and says, “After you!”. Big block steps in, does it’s little evaluation, and for each element that returns true, we shovel said element into the <code class="highlighter-rouge">extracted_elements</code> variable.</p>
<hr />
<h3 id="is-extract-actually-better-than-partition">Is extract! Actually Better than Partition?</h3>
<p><a href="https://github.com/rails/rails/pull/33137#issuecomment-397527806">Take a look at the benchmark</a> that compares the methods to see which ones are faster!</p>
<p>At our Continuations meeting this week, <a href="https://twitter.com/AaronLasseigne">@AaronLasseigne</a> also suggested trying <code class="highlighter-rouge">#with_object</code> to see if we could make this method sandwich an unwich. Here’s the method, which does indeed function appropriately.</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">def</span> <span class="nf">extract!</span>
<span class="k">return</span> <span class="n">to_enum</span><span class="p">(</span><span class="ss">:extract!</span><span class="p">)</span> <span class="p">{</span> <span class="n">size</span> <span class="p">}</span> <span class="k">unless</span> <span class="nb">block_given?</span>
<span class="n">reject!</span><span class="p">.</span><span class="nf">with_object</span><span class="p">([])</span> <span class="k">do</span> <span class="o">|</span><span class="n">element</span><span class="p">,</span> <span class="n">extracted_elements</span><span class="o">|</span>
<span class="n">extracted_elements</span> <span class="o"><<</span> <span class="n">element</span> <span class="k">if</span> <span class="k">yield</span><span class="p">(</span><span class="n">element</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span></code></pre></figure>
<p>But when I ran the benchmark similar to Bogdan’s, it turns out that it didn’t run as fast as his. But it was worth a try! The results using <code class="highlighter-rouge">#with_object</code> are from <code class="highlighter-rouge">Array#extract_v3!</code></p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Warming up --------------------------------------
Array#partition 1.000 i/100ms
Array#extract_v1! 1.000 i/100ms
Array#extract_v2! 1.000 i/100ms
Array#extract_v3! 1.000 i/100ms
Calculating -------------------------------------
Array#partition 0.807 (± 0.0%) i/s - 4.000 in 5.002523s
Array#extract_v1! 1.601 (± 0.0%) i/s - 8.000 in 5.073510s
Array#extract_v2! 1.772 (± 0.0%) i/s - 9.000 in 5.079500s
Array#extract_v3! 1.516 (± 0.0%) i/s - 8.000 in 5.285609s
Comparison:
Array#extract_v2!: 1.8 i/s
Array#extract_v1!: 1.6 i/s - 1.11x slower
Array#extract_v3!: 1.5 i/s - 1.17x slower
Array#partition: 0.8 i/s - 2.20x slower
</code></pre></div></div>A couple weeks ago I got my standard This Week in Rails newsletter, and saw that someone had added the extract! “Extract Bang” method to the Array class in Rails (Active Support):GitHub Stickers2018-02-13T20:15:00+00:002018-02-13T20:15:00+00:00/github/2018/02/13/GitHub-Stickers<p>I need to clean up my Jekyll posting process, because I have to break into the repo and duplicate a file, then change some meta data and content before publishing. I like that I own the site, but the publishing process could be improved. Anyway, I got hired as a Software Engineer doing Ruby on Rails in early October 2017, so I’ve been at it a little over four measly months. I’d like to tell you more about it, but I’ll start by saying I’m really trying to understand Git and GitHub, so I started teaching a class at Dallas Makerspace. When I ordered <a href="https://github.myshopify.com/collections/all-products/products/octodex-sticker-packs">stickers from GitHub</a>, I wasn’t sure exactly what I was getting, so in an effort to help others who also won’t know, here you go:</p>
<h2 id="pack-3">Pack 3</h2>
<p><img src="/assets/github_stickers_pack_3.JPG" alt="GitHub Stickers Pack 3" /></p>
<h2 id="pack-5">Pack 5</h2>
<p><img src="/assets/github_stickers_pack_5.JPG" alt="GitHub Stickers Pack 5" /></p>I need to clean up my Jekyll posting process, because I have to break into the repo and duplicate a file, then change some meta data and content before publishing. I like that I own the site, but the publishing process could be improved. Anyway, I got hired as a Software Engineer doing Ruby on Rails in early October 2017, so I’ve been at it a little over four measly months. I’d like to tell you more about it, but I’ll start by saying I’m really trying to understand Git and GitHub, so I started teaching a class at Dallas Makerspace. When I ordered stickers from GitHub, I wasn’t sure exactly what I was getting, so in an effort to help others who also won’t know, here you go:RSpec Hidden Config Hell2017-10-02T17:36:00+00:002017-10-02T17:36:00+00:00/ruby/rspec/2017/10/02/RSpec-Hidden-Config-Hell<p>I’m over 50% through the Lynda course <a href="https://www.lynda.com/Ruby-tutorials/RSpec-Testing-Framework-Ruby/183884-2.html">Ruby: Testing with RSpec</a>. I’ve seen the basics and even built a <a href="https://github.com/chemturion/rubystems/blob/master/rspec_question_bank.md">hefty question bank</a> for the Rubystems app I have in mind. But I hit a roadblock about an hour ago in the Challenges section and finally broke through. Here’s what happened and here’s what I did to get past it:</p>
<h2 id="damn-outdated-material">Damn Outdated Material</h2>
<p>Last week as I was going thru the Rails 5: Integrating Stripe course, I was disappointed that Stripe is now version 3 and the course was on version 2, leaving me stranded and unable to complete the tutorial. So whenever my app’s behavior deviated from the Lynda course, needless to say I went to my gut explanation: the versions I’m working on and the tutorial’s versions have screwed everything up! I was wrong.</p>
<h3 id="tldr">TL;DR</h3>
<blockquote>
<p>Copying sample files into your working directory excludes the hidden “dotfiles”. So when you’re expecting there to be <code class="highlighter-rouge">.rspec</code> containing <code class="highlighter-rouge">--require spec_helper.rb</code>, your tests will go haywire.</p>
</blockquote>
<h2 id="the-long-story">The Long Story</h2>
<p>My first error was <code class="highlighter-rouge">NameError</code>, and it seemed as though my spec file didn’t know about <code class="highlighter-rouge">APP_ROOT</code>:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">Failures:
1<span class="o">)</span> Guide includes NumberHelper and <span class="c">#number_to_currency</span>
Failure/Error: @filepath <span class="o">=</span> File.join<span class="o">(</span>APP_ROOT, path<span class="o">)</span>
NameError:
uninitialized constant RestaurantFile::APP_ROOT
<span class="c"># ./lib/restaurant_file.rb:12:in `filepath='</span>
<span class="c"># ./lib/restaurant_file.rb:7:in `initialize'</span>
<span class="c"># ./lib/restaurant.rb:14:in `new'</span>
<span class="c"># ./lib/restaurant.rb:14:in `load_file'</span>
<span class="c"># ./lib/guide.rb:15:in `initialize'</span>
<span class="c"># ./spec/guide_spec.rb:6:in `new'</span>
<span class="c"># ./spec/guide_spec.rb:6:in `block (2 levels) in <top (required)>'</span>
<span class="c"># ./spec/guide_spec.rb:18:in `block (2 levels) in <top (required)>'</span></code></pre></figure>
<p>I knew that <code class="highlighter-rouge">init.rb</code> defined <code class="highlighter-rouge">APP_ROOT</code>, and that the app worked fine when running <code class="highlighter-rouge">ruby init.rb</code>. So then my question was, “Why doesn’t the spec file know about <code class="highlighter-rouge">APP_ROOT</code> when running <code class="highlighter-rouge">rspec</code>?” I did some googling and then would place some “puts” statements here and there to see output when running tests. I also would redefine <code class="highlighter-rouge">APP_ROOT</code> locally in each file to see the behavior. I traced it down from the spec to the <code class="highlighter-rouge">filepath=</code> call in <code class="highlighter-rouge">restaurant_file.rb</code>, and all the way back to <code class="highlighter-rouge">guide_spec.rb</code>.</p>
<p>Typically the first line in the error trace thing is the line that needs fixing, and then voila— all the other errors with dependency vanish. But this guy was tricky in that I needed to investigate <code class="highlighter-rouge">guide_spec.rb</code>… all the way at the bottom of the <code class="highlighter-rouge">NameError</code> message.</p>
<p>Once inside <code class="highlighter-rouge">guide_spec.rb</code> I kept asking myself how this file should know about other files and their code. Then I remembered <code class="highlighter-rouge">spec_helper.rb</code>. So I looked in there and whadayaknow:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># The spec_helper file is the place for loading up any code needed</span>
<span class="c1"># by all tests (especially the code being targeted by the tests).</span>
<span class="nb">require</span> <span class="s1">'guide'</span>
<span class="c1"># Set the application root for easy reference.</span>
<span class="no">APP_ROOT</span> <span class="o">=</span> <span class="no">File</span><span class="p">.</span><span class="nf">expand_path</span><span class="p">(</span><span class="s1">'../..'</span><span class="p">,</span> <span class="kp">__FILE__</span><span class="p">)</span></code></pre></figure>
<p>I could have explicitly required <code class="highlighter-rouge">spec_helper.rb</code> in my spec file, but that comment up top about “loading up any code needed by all tests…” was the key. “How does my spec file know about the spec helper?” Is it some Ruby or RSpec magic? Well, there is no magic; just obfuscation. Then I got the bright idea to run <code class="highlighter-rouge">cat .rspec</code> in my terminal, and got <code class="highlighter-rouge">cat: .rspec: No such file or directory</code>.</p>
<p>It seems as though code newbies could benefit from a class on common “gotchas”. Configuration and gotchas seem to be a huge time-suck for folks in their first rodeo. Anyway, I’m gonna get back to writing RSpec now.</p>I’m over 50% through the Lynda course Ruby: Testing with RSpec. I’ve seen the basics and even built a hefty question bank for the Rubystems app I have in mind. But I hit a roadblock about an hour ago in the Challenges section and finally broke through. Here’s what happened and here’s what I did to get past it:Simple CMS and Atomic Commits2017-09-17T20:36:00+00:002017-09-17T20:36:00+00:00/rails/2017/09/17/simple-cms<p>I’ve been off the radar lately because I’ve been heads down in <a href="https://www.lynda.com/Ruby-Rails-tutorials/Ruby-Rails-5-Essential-Training/500551-2.html">Ruby on Rails 5 Essential Training</a>. But I’m back in the blog because I just finished! Special thanks to <a href="https://www.linkedin.com/in/kirk-keeter-8943b6/">Kirk Keeter</a> for teaching his free “Build Web/Mobile Apps with Ruby on Rails, Node.js and React.js” class at Dallas Makerspace. This course was part of the homework for that class, and although I had watched the course before, I went through it beginning to end, even not peeking at the solutions when given challenges. I was surprised at how close my code resembled Kevin Skoglund’s answers. I also practiced atomic commits during this course, and now when I progress too far, or feel myself venturing outside the scope of my current task, I feel a force pulling me back.</p>
<p>I’ve still got a lot to learn, and I never want to stop. I probably work too much, even to the point that I called my girlfriend “Ruby” the other day. That’s not her name, and I had to explain that even though I’d fallen in love Ruby, she had nothing to worry about. I’ve been in this zone before where my focus filters my physical reality. When Nintendo 64 came out, I played Golden Eye so obsessively for hours at a time that when I reentered the real world, things would still look 64-bit to me. I also experienced this filtering when I played Gears of War a few years back. That’s what it takes to get into the top 100 on the leaderboards, I suppose! I want to do the same with Ruby, Rails, and whatever else I dive into. Basically become a top 1% programmer.</p>I’ve been off the radar lately because I’ve been heads down in Ruby on Rails 5 Essential Training. But I’m back in the blog because I just finished! Special thanks to Kirk Keeter for teaching his free “Build Web/Mobile Apps with Ruby on Rails, Node.js and React.js” class at Dallas Makerspace. This course was part of the homework for that class, and although I had watched the course before, I went through it beginning to end, even not peeking at the solutions when given challenges. I was surprised at how close my code resembled Kevin Skoglund’s answers. I also practiced atomic commits during this course, and now when I progress too far, or feel myself venturing outside the scope of my current task, I feel a force pulling me back.Tutorial Deviations2017-09-11T23:42:00+00:002017-09-11T23:42:00+00:00/rails/2017/09/11/tutorial-deviations<p>I’ve been going thru Lynda’s Rails 5 Essentials by Kevin Skoglund today and finished chapter 4. This Lynda course is part of a class I’m in at Dallas Makerspace on creating Rails & React apps. Here’s <a href="https://github.com/chemturion/content-management-system">my repo for the simple content management system</a>.</p>
<p>I’ve been practicing “atomic commits”, and today got up to 40. <a href="https://github.com/chemturion/content-management-system/commits/master">https://github.com/chemturion/content-management-system/commits/master</a></p>
<p>I also tried the challenge at the end of chapter 4 and went a step further to create the model associations in addition to the foreign key definitions in the database migrations. The default migration method is <code class="highlighter-rouge">#change</code>, and Skoglund has us splitting this method into <code class="highlighter-rouge">#up</code> and <code class="highlighter-rouge">#down</code>. Unfortunately I got careless in my Section migration and didn’t change my <code class="highlighter-rouge">drop_table :sections</code> call to the <code class="highlighter-rouge">#down</code> method. So I had <a href="https://github.com/chemturion/content-management-system/commit/4605f9791c2c23119af6e5a45b6dd200728b47c9">TWO <code class="highlighter-rouge">#up</code> methods</a>! So I was able to <code class="highlighter-rouge">rails db:migrate</code> and <code class="highlighter-rouge">rails db:migrate:status</code> no problem, but my schema didn’t have a Sections table. That was a fun 20 minutes of troubleshooting. I can see how tests would help point out this deviation.</p>
<p>Kevin also created foreign keys a bit different. In his Section migration, inside the <code class="highlighter-rouge">#up</code> > <code class="highlighter-rouge">create_table...</code> he has <code class="highlighter-rouge">t.integer :page_id</code>, and outside of <code class="highlighter-rouge">create_table...</code> he has <code class="highlighter-rouge">add_index "sections", "page_id"</code>.</p>
<p>I went a different route: <code class="highlighter-rouge">t.belongs_to :page, foreign_key: true, index: true</code>. So we ended up with different schemas. His page_id was an integer, whereas mine resolved (after the migration) to a bigint. His t.index had an additional option at the end: <code class="highlighter-rouge">using: :btree</code>. I have no idea what this means, and just making the observation at this point.</p>
<p><strong>Onward!</strong></p>I’ve been going thru Lynda’s Rails 5 Essentials by Kevin Skoglund today and finished chapter 4. This Lynda course is part of a class I’m in at Dallas Makerspace on creating Rails & React apps. Here’s my repo for the simple content management system.Code Quiz2017-09-09T15:00:00+00:002017-09-09T15:00:00+00:00/programming/learning/2017/09/09/code-quiz<p>I’ve wanted to create a web app similar to Code Wars for some time now. Several tutorials have quizzes built into their lessons, but they never do them completely well and they only supplement the lesson. I think a web app (and a mobile app) would be a good way for learners to stay sharp when they don’t have the focus or time for proper programming. I’d also like to make the thing open source similar to the Odin Project.</p>
<p>I don’t want to tarry long, so here’s an example quiz problem.</p>
<h4 id="the-reduce-method-alias">The Reduce Method Alias</h4>
<p>Some Ruby methods have aliases (for example, you can call <code class="highlighter-rouge">#length</code> or <code class="highlighter-rouge">#size</code> on an array; these two methods do the same thing) The <code class="highlighter-rouge">#reduce</code> method can sum an array of numbers, like so <code class="highlighter-rouge">[5, 6, 7, 8, 9, 10].reduce(:+) # => 45</code>. Which of the following is the only alias of the <code class="highlighter-rouge">#reduce</code> method?</p>
<ul>
<li><code class="highlighter-rouge">#inspect</code></li>
<li><code class="highlighter-rouge">#inject</code></li>
<li><code class="highlighter-rouge">#group_by</code></li>
<li><code class="highlighter-rouge">#select</code></li>
<li><code class="highlighter-rouge">#sum</code></li>
</ul>
<p>The user would then select their answer, and either click a button to check their answer or the check would be revealed upon selection. Probably the latter for a better user experience. But it wouldn’t be just a boolean “Correct” or “Incorrect”. Each choice would have an explanation as to why it was right or wrong; true or false.</p>
<p>You’ll notice I made all the multiple choice options reasonably feasible answers. Having a choice like <code class="highlighter-rouge">#foobarbaz</code> wouldn’t be incredibly constructive. If <code class="highlighter-rouge">#inspect</code> is selected (which is alphabetically near to the correct answer), the user would see that it’s incorrect (some CSS animation showing a red X) and a message as to why it was incorrect, like “The #inspect method is used instead of #to_s to get a more detailed description of the object in question. <a href="http://railsmaster.net/2016/09/23/inspect-and-to-s-in-ruby-classes/">Read more at railsmaster.net</a>.”</p>
<p>The remaining options would look as follows when selected:</p>
<ul>
<li><code class="highlighter-rouge">#inject</code>
<blockquote>
<p>Correct! The #inject method is the same as #reduce. <a href="https://martinfowler.com/articles/collection-pipeline/reduce.html">Read more here for some history of the alias.</a>.</p>
</blockquote>
</li>
<li><code class="highlighter-rouge">#group_by</code>
<blockquote>
<p>Incorrect. <a href="https://ruby-doc.org/core-2.4.1/Enumerable.html#method-i-group_by">#group_by</a> iterates over an array and returns a hash where the key/value pairs are the grouping condition and matching elements, respectively.</p>
</blockquote>
</li>
<li><code class="highlighter-rouge">#select</code>
<blockquote>
<p>Incorrect. <a href="https://ruby-doc.org/core-2.4.1/Enumerable.html#method-i-select">#select</a> is used to return a new array of elements that match some condition.</p>
</blockquote>
</li>
<li><code class="highlighter-rouge">#sum</code>
<blockquote>
<p>Incorrect. Although the example of summing values in an array was used, Ruby does not have a #sum method built in, and #reduce can do more than add values together. For example, we could have multiplied all the array elements: <code class="highlighter-rouge">[5, 6, 7, 8, 9, 10].reduce(:*) # => 151200</code></p>
</blockquote>
</li>
</ul>
<p>Going through that exercise was honestly a bit grueling. At first glance, the methods seemed close enough to warrant differentiation. But the process of providing meaningful explanations was a bit tough to contrast. Five choices is probably the max I’d want in choices, and if the question isn’t asking for “True” or “False”, a minimum of three choices would be good. I’d still like to see explanations to provide rationale for why an incorrect choice was supplied.</p>
<p>…</p>
<p>So that’s the gist of what I’d like to build. Time to create a new repo for this project. https://github.com/chemturion/rubystem</p>I’ve wanted to create a web app similar to Code Wars for some time now. Several tutorials have quizzes built into their lessons, but they never do them completely well and they only supplement the lesson. I think a web app (and a mobile app) would be a good way for learners to stay sharp when they don’t have the focus or time for proper programming. I’d also like to make the thing open source similar to the Odin Project.Rails 5 render() in the Controller2017-09-07T03:47:00+00:002017-09-07T03:47:00+00:00/rails/2017/09/07/rails-render<p>I’ve written a few times already about being verbose and concrete when teaching and learning programming. This best practice is especially relevant to learning Ruby on Rails, where so much functionality is obfuscated. For example, how does my Rails app know which template to render when a route is requested? When I navigate to <code class="highlighter-rouge">localhost:3000/about</code> in my browser, I’m requesting the About page (I want this Rails app to render a particular template). The <code class="highlighter-rouge">routes.rb</code> file has the corresponding route code:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="no">Rails</span><span class="p">.</span><span class="nf">application</span><span class="p">.</span><span class="nf">routes</span><span class="p">.</span><span class="nf">draw</span> <span class="k">do</span>
<span class="n">get</span> <span class="s1">'/about'</span><span class="p">,</span> <span class="ss">to: </span><span class="s1">'home#about'</span><span class="p">,</span> <span class="ss">as: :about</span>
<span class="k">end</span></code></pre></figure>
<p>The route’s job is only to match the HTTP verb, in this case <strong>GET</strong>, and some string, in this case <strong>/about</strong>. The <code class="highlighter-rouge">routes.rb</code> file in effect now says, “Go to the <strong>Home</strong> controller and see the <code class="highlighter-rouge">#about</code> method for further instructions. And let’s just say among friends that this reference is known <em>as ‘about’</em>.” Ok, let’s follow the breadcrumbs and see what awaits us:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># app/controllers/home_controller.rb</span>
<span class="k">class</span> <span class="nc">HomeController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
<span class="k">end</span></code></pre></figure>
<p>Umm.. where to next? Seems like we’ve reached a dead end. Rather than being explicit and verbose, Rails obfuscates its default behavior, which in this case is to look for a template named “about” in the directory <code class="highlighter-rouge">app/views/home</code>. It is precisely this convention in Rails that makes it simultaneously less difficult to develop in, and harder to understand as a newbie. So while we want to end up with the aforementioned controller code for our simple About page, let’s build it up with verbosity. It’s almost as if I’m tapping the controller with a magic wand, and watching the obfuscated code appear.</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">HomeController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
<span class="k">def</span> <span class="nf">about</span>
<span class="k">end</span>
<span class="k">end</span></code></pre></figure>
<p>So coming from Ruby, it looks like we just have an inherited class with an instance method definition sans logic. This code works and will render the About page; same as before, just a tad more explicit. But it’s still obfuscating the <code class="highlighter-rouge">#render</code> method. Let’s throw that in:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">HomeController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
<span class="k">def</span> <span class="nf">about</span>
<span class="n">render</span>
<span class="k">end</span>
<span class="k">end</span></code></pre></figure>
<p>Looks similar to <code class="highlighter-rouge">return</code> or <code class="highlighter-rouge">raise</code> in Ruby. Simple. Let’s take it another step, by telling it <em>what</em> to render:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">HomeController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
<span class="k">def</span> <span class="nf">about</span>
<span class="n">render</span> <span class="s2">"about"</span>
<span class="k">end</span>
<span class="k">end</span></code></pre></figure>
<p>Ok, but what is “about”, exactly? We want the “about” template located at <code class="highlighter-rouge">app/views/home</code>, so let’s be more explicit:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">HomeController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
<span class="k">def</span> <span class="nf">about</span>
<span class="n">render</span> <span class="ss">template: </span><span class="s2">"about"</span>
<span class="k">end</span>
<span class="k">end</span></code></pre></figure>
<p>Drats! We get the following error now, which means that when using the <code class="highlighter-rouge">template:</code> argument, the path must become explicit:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Template is missing
Missing template /about with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :coffee, :jbuilder, :haml]}. Searched in: * "/Users/kelton/Sites/narify/app/views"
</code></pre></div></div>
<p>Let’s make the path more explicit so it knows to look inside the <code class="highlighter-rouge">home</code> folder inside <code class="highlighter-rouge">views</code>:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">HomeController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
<span class="k">def</span> <span class="nf">about</span>
<span class="n">render</span> <span class="ss">template: </span><span class="s2">"home/about"</span>
<span class="k">end</span>
<span class="k">end</span></code></pre></figure>
<p>Alright, at this point you can probably see some duplication (which is why Rails obfuscates this if it can). We have <code class="highlighter-rouge">class HomeController</code> and <code class="highlighter-rouge">def about</code> followed by the <code class="highlighter-rouge">render template:</code> method where we’re repeating our controller and method: <code class="highlighter-rouge">"home/about"</code>. I personally like to be even more explicit, like so:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">HomeController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
<span class="k">def</span> <span class="nf">about</span>
<span class="n">render</span> <span class="ss">template: </span><span class="s2">"/app/views/home/about.html.haml"</span>
<span class="k">end</span>
<span class="k">end</span></code></pre></figure>
<p>But this code is even more illustrative regarding the path, as evidenced by the error I get in my browser:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Template is missing
Missing template app/views/home/about.html.haml with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :coffee, :jbuilder, :haml]}. Searched in: * "/Users/kelton/Sites/narify/app/views"
</code></pre></div></div>
<p>Particularly that last bit: <code class="highlighter-rouge">Searched in: * "/Users/~/Sites/narify/app/views"</code>. If I’m not mistaken, the full path being searched would be <code class="highlighter-rouge">/Users/kelton/Sites/narify/app/views/app/views/home/about.html.haml</code>, so we could reasonably assert that we only need to specify the contents within the <code class="highlighter-rouge">views</code> folder, i.e. a relative path.</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">HomeController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
<span class="k">def</span> <span class="nf">about</span>
<span class="n">render</span> <span class="ss">template: </span><span class="s2">"home/about.html.haml"</span>
<span class="k">end</span>
<span class="k">end</span></code></pre></figure>
<blockquote>
<p><code class="highlighter-rouge">render template: "home/about.html"</code> also works, but not <code class="highlighter-rouge">render template: "home/about.haml"</code></p>
</blockquote>
<p>I’m going to start being explicit in my controllers’ <code class="highlighter-rouge">#render</code> methods. Similar to the testing mantra of “test until fear turns to boredom”, I’m going to explicitly render until I’m comfortable with the obfuscated version. Only now will I not take any magic for granted, nor will I fail to understand what’s <em>actually</em> happening. You might think that overriding the obfuscated render could produce unwanted side effects, and that would be a reason for not being explicit. But I’d argue that such an event would be yet another opportunity to better understand this method and how it relates to the rest of our application.</p>I’ve written a few times already about being verbose and concrete when teaching and learning programming. This best practice is especially relevant to learning Ruby on Rails, where so much functionality is obfuscated. For example, how does my Rails app know which template to render when a route is requested? When I navigate to localhost:3000/about in my browser, I’m requesting the About page (I want this Rails app to render a particular template). The routes.rb file has the corresponding route code:Bash Profile and cmd + delete2017-09-05T15:20:00+00:002017-09-05T15:20:00+00:00/fail/2017/09/05/bash-profile-and-cmd-delete<p>I’ve been taking the <a href="https://www.lynda.com/Mac-OS-X-10-6-tutorials/Unix-for-Mac-OS-X-Users/78546-2.html?org=dallaslibrary.org">Unix for Mac OS X Users</a> course on Lynda, and decided to venture out on my own by editing my <code class="highlighter-rouge">.bash_profile</code> file. I already had some <code class="highlighter-rouge">PS1</code> lines, and another for setting the Ruby environment, so I inserted a harmless line: <code class="highlighter-rouge">echo "edit your shell startup in .bash_profile"</code> so I’d see that line every time I started my terminal program. Unfortunately when I restarted my terminal, it became inoperable! So I can’t <code class="highlighter-rouge">nano .bash_profile</code> to fix it either.</p>
<p>Now I’m on the hunt for how to access the <code class="highlighter-rouge">.bash_profile</code> file using Finder. Unfortunately it’s quite difficult to view hidden files on one’s machine, and I always have to google the keyboard shortcut because for some reason you can’t simply find the option in the menu. I don’t want to repeat what I’ve done in the past (because I’m lazy)…</p>
<p>So then I decide to use Spotlight. I move my fingers to <code class="highlighter-rouge">cmd + spacebar</code>, type in “.bash_profile”, and… nothing. So I then use my nimble fingers to erase that query in one-fail-swoop using <code class="highlighter-rouge">cmd + delete</code>, but instead of erasing the search parameter, I hear the sound of files being chunked into the trash. No problem (I thought)! I’ll just undo that operation.</p>
<p>Well, when you select multiple files from the trash, there is no option to “put back” each into their respective directories whence they came. Instead, you’ve got to select individual files to perform that operation. Wow, I’m learning so much this morning!</p>
<p>Ok, so I looked up the keyboard shortcut again to view hidden files and folders. I would link to the website where I got the info, but macworld.co.uk has a shit-ton of ads, videos, and x-knows-what-else (I can see the browser tab’s favicon spasming into the reload icon), resulting in glitchy scrolling and an overall very poor user experience, so I’ll spare you the misery.</p>
<p><code class="highlighter-rouge">cmd + shift + .</code> to view hidden files and folders from Finder.</p>I’ve been taking the Unix for Mac OS X Users course on Lynda, and decided to venture out on my own by editing my .bash_profile file. I already had some PS1 lines, and another for setting the Ruby environment, so I inserted a harmless line: echo "edit your shell startup in .bash_profile" so I’d see that line every time I started my terminal program. Unfortunately when I restarted my terminal, it became inoperable! So I can’t nano .bash_profile to fix it either.Codewars: My First Kata — Clear the Catacombs!2017-08-30T19:24:00+00:002017-08-30T19:24:00+00:00/ruby/codewars/2017/08/30/codewars-my-first-kata<p>You’ll never guess how much Codewars paid me to create <a href="https://www.codewars.com/kata/clear-the-catacombs/train/ruby">a problem for their website</a>…</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">payment</span><span class="p">.</span><span class="nf">zero?</span> <span class="c1"># => true</span></code></pre></figure>
<p>This crowdsourced phenomenon that derives their content is similar to my business model for Narify: people giving of their time and effort to create something for their own, and everyone else’s, gain. So yes, I created <a href="https://www.codewars.com/kata/clear-the-catacombs/train/ruby">a very simple but thoughtful Kata</a>, or so I thought.</p>
<p>Here’s the problem statement:</p>
<blockquote>
<p>There are many ways to clear the catacombs, er um, I mean methods to modify your strings! Let’s say you’ve got a string called <code class="highlighter-rouge">catacombs</code>, and it’s full of spiders and bats, like so:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">catacombs</span> <span class="o">=</span> <span class="s2">"spiders and bats!"</span>
</code></pre></div> </div>
<p>While you may be tempted to call <code class="highlighter-rouge">catacombs.overtune</code> to clear the catacombs, unfortunately that’s an undefined method in Ruby!</p>
<p>Your job is to find and use the method on the <code class="highlighter-rouge">catacombs</code> so that it’s cleared and returns an empty string. Good luck!</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">clearify</span><span class="p">(</span><span class="s2">"spiders and bats!"</span><span class="p">)</span> <span class="c1"># => ""</span>
</code></pre></div> </div>
</blockquote>
<p>It started by me wanting a quick and easy win for my first attempt. So I looked at the <a href="https://ruby-doc.org/core-2.3.0/String.html">Ruby docs’</a> String methods, and found <a href="https://ruby-doc.org/core-2.3.0/String.html#method-i-clear">the <code class="highlighter-rouge">#clear</code> method</a>. So easy! Take a string like <code class="highlighter-rouge">catacombs = "spiders and bats!"</code>, then run <code class="highlighter-rouge">catacombs.clear # => ""</code> to return an empty string. I thought this would be a good String method for newbies to learn. Sure, you could reassign the variable like so: <code class="highlighter-rouge">catacombs = ""</code>. But that assumes your variable already exists. If not, you’ve just created a new variable set to an empty string. Another thing that reassignment does is it changes your object_id!</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">catacombs <span class="o">=</span> <span class="s2">"spiders and bats!"</span>
<span class="o">=></span> <span class="s2">"spiders and bats!"</span>
catacombs.object_id
<span class="o">=></span> 70232165920920
catacombs <span class="o">=</span> <span class="s2">""</span>
<span class="o">=></span> <span class="s2">""</span>
catacombs.object_id
<span class="o">=></span> 70232169423060</code></pre></figure>
<p>Also, reassignment can work on most, if not any, unfrozen variable of any data type. And this reassignment will slip by silently when an error might be more appropriate. For example:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">catanums <span class="o">=</span> 1
<span class="o">=></span> 1
catanums.clear
NoMethodError: undefined method <span class="sb">`</span>clear<span class="s1">' for 1:Integer</span></code></pre></figure>
<p>Here’s the desired solution with object id inspection:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">catacombs <span class="o">=</span> <span class="s2">"spiders and bats!"</span>
<span class="o">=></span> <span class="s2">"spiders and bats!"</span>
catacombs.object_id
<span class="o">=></span> 70232169411420
catacombs.clear
<span class="o">=></span> <span class="s2">""</span>
catacombs.object_id
<span class="o">=></span> 70232169411420</code></pre></figure>
<p>Creating the description wasn’t that difficult because I’m used to using Markdown for this Jekyll blog. The difficult part was writing the tests, because 1) I’m not incredibly familiar with writing Ruby tests, and 2) I’m not familiar with Codewars’ test suite. And while I was able to test that the method which houses where <code class="highlighter-rouge">catacombs.clear</code> should return zero, I wasn’t able to test that the <code class="highlighter-rouge">catacombs</code> variable was changed to zero. I need to go back and do that. Also, I need to check that the object_id remains the same, otherwise you could pass the Kata by simply returning <code class="highlighter-rouge">''</code>. Not what I intended. Moreover, out of its 6 completions so far, 3 have voted on its Satisfaction rating: 1 for “Somewhat Satisfied” and 2 for “Not Satisfied”. 2 of the 6 solutions were mine, and hey!— whaddayaknow!— There’s three people who submitted this answer:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">def</span> <span class="nf">clearify</span><span class="p">(</span><span class="n">catacombs</span><span class="p">)</span>
<span class="s1">''</span>
<span class="k">end</span></code></pre></figure>
<p>OK, so I’ve since updated my tests as follows:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="no">Test</span><span class="p">.</span><span class="nf">assert_equals</span><span class="p">(</span><span class="n">clearify</span><span class="p">(</span><span class="s2">"spiders and bats!"</span><span class="p">),</span> <span class="s2">""</span><span class="p">)</span>
<span class="no">Test</span><span class="p">.</span><span class="nf">expect_error</span><span class="p">(</span><span class="s2">"Both function and variable should return an empty string using a particular method. Try again or go to https://ruby-doc.org/core-2.3.0/String.html"</span><span class="p">)</span> <span class="p">{</span> <span class="n">clearify</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">}</span></code></pre></figure>
<p>The second test is only run on the final attempt, so answers like <code class="highlighter-rouge">''</code> or <code class="highlighter-rouge">catacombs = ''</code> will work initially, but fail upon final submission. This test forces the user to employ the <code class="highlighter-rouge">#clear</code> method. The testing documentation wasn’t helpful in getting the <code class="highlighter-rouge">Test.expect_error</code> to work, so I had to go looking for someone else’s example. Lessons learned, and I hope to make many more Katas. :)</p>
<p>Here’s the link to the Kata in full: <a href="https://www.codewars.com/kata/clear-the-catacombs/train/ruby">https://www.codewars.com/kata/clear-the-catacombs/train/ruby</a></p>You’ll never guess how much Codewars paid me to create a problem for their website…Ruby Singleton: Ballon d’Or2017-08-29T23:39:00+00:002017-08-29T23:39:00+00:00/ruby/soccer/2017/08/29/ruby-singleton<p>Every year FIFA selects the best soccer player in the world. There can only be one. My guess is that this year (2017), Cristiano Ronaldo will match Lionel Messi with his fifth Ballon d’Or (Golden Ball). So how can we model this in Ruby using the Singleton pattern?</p>
<p>The Singleton pattern ensures that a particular class can only have one instance of itself. Let’s try to build this from scratch:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">GoldenBall</span>
<span class="k">end</span></code></pre></figure>
<p>Presently this code is the foundation for any regular class in Ruby. <code class="highlighter-rouge">GoldenBall.new</code> will create a new object each time it’s invoked. Not good. There can only be one.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">ronaldo <span class="o">=</span> GoldenBall.new
<span class="o">=></span> <span class="c">#<GoldenBall:001></span>
messi <span class="o">=</span> GoldenBall.new
<span class="o">=></span> <span class="c">#<GoldenBall:002></span></code></pre></figure>
<p>We should be able to create a <code class="highlighter-rouge">ronaldo</code> instance of the GoldenBall class, but not a <code class="highlighter-rouge">messi</code> instance. Sorry Leo. Our <code class="highlighter-rouge">GoldenBall</code> class should know about itself, and how many instances has been created. Let’s try using a class variable, <code class="highlighter-rouge">@@instances</code>. Each time we create a new instance, let’s capture it therein.</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">GoldenBall</span>
<span class="c1"># define the class variable as an empty array</span>
<span class="vc">@@instances</span> <span class="o">=</span> <span class="p">[]</span>
<span class="c1"># when initialized, push the instance of the new</span>
<span class="c1"># GoldenBall class into the class variable array</span>
<span class="k">def</span> <span class="nf">initialize</span>
<span class="vc">@@instances</span> <span class="o"><<</span> <span class="nb">self</span>
<span class="k">end</span>
<span class="c1"># provide a method to access the instances array</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">instances</span>
<span class="vc">@@instances</span>
<span class="k">end</span>
<span class="k">end</span></code></pre></figure>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">ronaldo <span class="o">=</span> GoldenBall.new
<span class="o">=></span> <span class="c">#<GoldenBall:001></span>
GoldenBall.instances
<span class="o">=></span> <span class="o">[</span><span class="c">#<GoldenBall:001>]</span>
messi <span class="o">=</span> GoldenBall.new
<span class="o">=></span> <span class="c">#<GoldenBall:002></span>
GoldenBall.instances
<span class="o">=></span> <span class="o">[</span><span class="c">#<GoldenBall:001>, #<GoldenBall:002>]</span></code></pre></figure>
<p>OK, so we’ve added the functionality to track our newly created instances. Each new instance is an object of the <code class="highlighter-rouge">GoldenBall</code> class, and that object is pushed into our <code class="highlighter-rouge">@@instances</code> class variable array. How can we prevent more than one instance being initialized? Let’s add some conditional logic to our <code class="highlighter-rouge">#initialize</code> method so that we only add the new instance if our array is empty.</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">GoldenBall</span>
<span class="c1"># define the class variable as an empty array</span>
<span class="vc">@@instances</span> <span class="o">=</span> <span class="p">[]</span>
<span class="c1"># when initialized, push the instance of the new</span>
<span class="c1"># GoldenBall class into the class variable array</span>
<span class="c1"># only if the array is empty</span>
<span class="k">def</span> <span class="nf">initialize</span>
<span class="vc">@@instances</span> <span class="o"><<</span> <span class="nb">self</span> <span class="k">if</span> <span class="vc">@@instances</span><span class="p">.</span><span class="nf">empty?</span>
<span class="k">end</span>
<span class="c1"># provide a method to access the instances array</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">instances</span>
<span class="vc">@@instances</span>
<span class="k">end</span>
<span class="k">end</span></code></pre></figure>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">ronaldo <span class="o">=</span> GoldenBall.new
<span class="o">=></span> <span class="c">#<GoldenBall:001></span>
GoldenBall.instances
<span class="o">=></span> <span class="o">[</span><span class="c">#<GoldenBall:001>]</span>
messi <span class="o">=</span> GoldenBall.new
<span class="o">=></span> <span class="c">#<GoldenBall:002></span>
GoldenBall.instances
<span class="o">=></span> <span class="o">[</span><span class="c">#<GoldenBall:001>]</span></code></pre></figure>
<p>Hmm. After creating <code class="highlighter-rouge">ronaldo</code> we were still able to create a second object <code class="highlighter-rouge">messi</code>, even though our <code class="highlighter-rouge">GoldenBall.instances</code> only holds a single <code class="highlighter-rouge">ronaldo</code> object. At this point, we have a <code class="highlighter-rouge">Singleish</code> design pattern; not a true <code class="highlighter-rouge">Singleton</code>. But even this <code class="highlighter-rouge">Singleish</code> implementation is an illusion. How can we actually determine <a href="https://stackoverflow.com/questions/14318079/how-do-i-list-all-objects-created-from-a-class-in-ruby">how many instances exist in memory</a>?</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">ObjectSpace.each_object<span class="o">(</span>GoldenBall<span class="o">)</span>.count
<span class="o">=></span> 2</code></pre></figure>
<p>What if instead of <em>not doing anything</em> on subsequent instantiation, we raise an error. That would prevent subsequent instances, right? Here’s my new initialize method:</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># GoldenBall class</span>
<span class="k">def</span> <span class="nf">initialize</span>
<span class="vc">@@instances</span><span class="p">.</span><span class="nf">empty?</span> <span class="p">?</span> <span class="vc">@@instances</span> <span class="o"><<</span> <span class="nb">self</span> <span class="p">:</span> <span class="k">raise</span>
<span class="k">end</span></code></pre></figure>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">ronaldo <span class="o">=</span> GoldenBall.new
<span class="o">=></span> <span class="c">#<GoldenBall:001></span>
GoldenBall.instances
<span class="o">=></span> <span class="o">[</span><span class="c">#<GoldenBall:001>]</span>
messi <span class="o">=</span> GoldenBall.new
RuntimeError:
from <span class="o">(</span>irb<span class="o">)</span>:9:in <span class="sb">`</span>initialize<span class="s1">'
from (irb):20:in `new'</span>
from <span class="o">(</span>irb<span class="o">)</span>:20
from /Users/~/.rbenv/versions/2.4.1/bin/irb:11:in <span class="sb">`</span><main><span class="s1">'
GoldenBall.instances
=> [#<GoldenBall:001>]</span></code></pre></figure>
<p>Well there we go! I’m sure there’s something missing, but this will do for a newbie. Sorry Leo.</p>Every year FIFA selects the best soccer player in the world. There can only be one. My guess is that this year (2017), Cristiano Ronaldo will match Lionel Messi with his fifth Ballon d’Or (Golden Ball). So how can we model this in Ruby using the Singleton pattern?