<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Steve Klabnik — Ruby &amp; Rails</title><description>Ruby, Ruby on Rails, and the web development ecosystem around them.</description><link>https://steveklabnik.com/</link><item><title>Docember</title><link>https://steveklabnik.com/writing/docember/</link><guid isPermaLink="true">https://steveklabnik.com/writing/docember/</guid><description>There are few things I appreciate more than using software projects that have good documentation. When I’m new to the project, documentation is invaluable for helping me get going. When I’m not new, good documentation helps me get the information I need to :shipit:. We say…</description><pubDate>Tue, 01 Dec 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;There are few things I appreciate more than using software projects that have good documentation. When I’m new to the project, documentation is invaluable for helping me get going. When I’m not new, good documentation helps me get the information I need to :shipit:.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We say programming is hard, and we hate bad code. So we practice writing code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We say writing docs is hard, and hate bad docs…&lt;/p&gt;
&lt;p&gt;— Some(@steveklabnik) (@steveklabnik) November 30, 2015&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;About a month ago, I was tweeting about this topic, and &lt;a href=&quot;https://mayeu.me/misc/2015/11/13/docember-one-month-to-improve-your-documentation.html&quot;&gt;several of us came up with an idea&lt;/a&gt;: similar to how November is &lt;a href=&quot;http://nanowrimo.org/&quot;&gt;National Novel Writing Month&lt;/a&gt;, why not have a similar month for programming?&lt;/p&gt;
&lt;p&gt;Here’s the idea: in December, let’s try to work on the documentation for the projects we work on. Make it 50k words like NaNoWriMo, make it &lt;a href=&quot;http://24pullrequests.com/&quot;&gt;24 pull requests&lt;/a&gt;, whatever floats your boat. Your future self will love you for it.&lt;/p&gt;</content:encoded></item><item><title>Rescuing Resque (again)</title><link>https://steveklabnik.com/writing/rescuing-resque-again/</link><guid isPermaLink="true">https://steveklabnik.com/writing/rescuing-resque-again/</guid><description>A long time ago, there was a big open source project, which was a huge part of the Rails world, but had almost no maintenance. This project was Resque, the go-to way to write background jobs for your Rails application. I attended a talk where the current maintainer was clearly…</description><pubDate>Wed, 28 Oct 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A long time ago, there was a big open source project, which was a huge part of the Rails world, but had almost no maintenance. This project was Resque, the go-to way to write background jobs for your Rails application. I attended a talk where the current maintainer was clearly getting burned out, and so, &lt;a href=&quot;/writing/resque--let-s-do-this/&quot;&gt;offered to help&lt;/a&gt;. The problem is, things have changed.&lt;/p&gt;
&lt;p&gt;It wasn’t just me. It was a bunch of people. We all used Resque, and loved it, and wanted to make it better. We made plans for a big 2.0 to pay off a bunch of technical debt, simplify the codebase, and add more features. A ton of people chipped in, I had some awesome remote pairing sessions. Things were good.&lt;/p&gt;
&lt;p&gt;But slowly, we all started to drift away. One contributor changed jobs. Another decided to spend more time with family. I got discouraged, and then, there was a strange situation in which I accidentally released an entirely straight-up broken version. So I got scared, released a fix, and basically never touched Resque again.&lt;/p&gt;
&lt;p&gt;Resque is used by a &lt;em&gt;lot&lt;/em&gt; of people:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://svbtleusercontent.com/rsoq8peusw08q_small.png&quot; alt=&quot;https://svbtleusercontent.com/rsoq8peusw08q_small.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Yet, it hasn’t seen a release in 18 months. The PRs are piling up. 2.0 is basically dead in the water. I’m not much of a fan of 2.0s anymore myself, at least, ones that don’t follow the “stability without stagnation” principles. I don’t use Resque myself anymore, and barely have enough time for my work, let alone my personal projects, let alone a project that I care about but only work on out of the goodness of my heart.&lt;/p&gt;
&lt;p&gt;I’m here to tell you that that’s changing a little bit. I’ve been chatting with &lt;a href=&quot;https://github.com/hoffmanc/&quot;&gt;Chris Hoffman&lt;/a&gt;, who’s interested in starting up on work again. I asked him what his intentions were, and what he answered with was exactly what I wanted to hear, as it turns out. So, I’m going to be doing some work again, this time, with the explicit intention of handing off maintenance to Chris and anyone else who wants to chip in. If you use Resque commercially, this is a great time to give some of your people the opportunity to give back. If you’ve never worked on an open source project before, but want to, I’d be more than happy to help mentor you with this. Resque is a big, real project, with a lot of impact. You can do a lot of good. That’s why I started working on it.&lt;/p&gt;
&lt;p&gt;Without further ado, here is The Plan, from Chris and I:&lt;/p&gt;
&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;change &lt;code&gt;master&lt;/code&gt; from unreleased 2.0 back to &lt;code&gt;1-x-stable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;clean up tests - make the development experience enjoyable&lt;/li&gt;
&lt;li&gt;integrate pending Pull Requests&lt;/li&gt;
&lt;li&gt;2.0? Never heard of it. At least, not for a while.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;make-1-x-stable-master-again&quot;&gt;Make &lt;code&gt;1-x-stable&lt;/code&gt; master again&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/resque/resque/issues/1175&quot;&gt;Many&lt;/a&gt; &lt;a href=&quot;https://github.com/resque/resque/issues/976&quot;&gt;have&lt;/a&gt; stated that the README on the master branch has led them astray, because the published gem is still at 1.25.2.&lt;/p&gt;
&lt;p&gt;We will plan on making this switch in the next couple of weeks. If you feel this is the wrong move, please let us know. But since active development will in fact happen on 1.x, this feels like the correct thing.&lt;/p&gt;
&lt;h2 id=&quot;fix-up-the-test-suite&quot;&gt;Fix up the test suite&lt;/h2&gt;
&lt;p&gt;Tests need to be fast, and clean, so that there is more incentive to contribute.&lt;/p&gt;
&lt;p&gt;One possible approach is using one of the available Redis mocking libraries (mock_redis, fakeredis) in non-forking tests, which could speed suite execution up considerably.&lt;/p&gt;
&lt;h2 id=&quot;review-pending-1-x-stable-prs&quot;&gt;Review Pending &lt;code&gt;1-x-stable&lt;/code&gt; PRs&lt;/h2&gt;
&lt;p&gt;This is the lion’s share of the work, as there are currently 56 (that’s &lt;em&gt;&lt;a href=&quot;https://github.com/resque/resque/pulls&quot;&gt;fifty six&lt;/a&gt;&lt;/em&gt;) open pull requests…&lt;/p&gt;
&lt;p&gt;&lt;em&gt;And that’s an awesome problem!&lt;/em&gt; Let’s make use of them! These PRs need to be evaluated and closed, so that the project can benefit from the community.&lt;/p&gt;
&lt;h2 id=&quot;decide-what-to-do-with-20&quot;&gt;Decide What to do with 2.0&lt;/h2&gt;
&lt;p&gt;The focus of Resque should be on stability, with an eye towards legacy support. 2.0 is off the table, at least in the near term.&lt;/p&gt;
&lt;p&gt;If there is a 2.0, it will be a “garbage collection”-style release, where only deprecated functionality is removed, and the upgrade path is clear.&lt;/p&gt;</content:encoded></item><item><title>Ember Data: ‘DS’ is not defined</title><link>https://steveklabnik.com/writing/ember-data--ds-is-not-defined/</link><guid isPermaLink="true">https://steveklabnik.com/writing/ember-data--ds-is-not-defined/</guid><description>I’m doing a little Ember app, and if there’s one thing I’ve learned from writing software, it’s to blog about error messages. Two-years-later me has ended up finding my own posts when searching for help! So today, when getting started with Ember Data 1.13, I was trying to use the…</description><pubDate>Sun, 05 Jul 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’m doing a little Ember app, and if there’s one thing I’ve learned from writing software, it’s to blog about error messages. Two-years-later me has ended up finding my own posts when searching for help!&lt;/p&gt;
&lt;p&gt;So today, when getting started with Ember Data 1.13, I was trying to use the new &lt;code&gt;JSONAPIAdapter&lt;/code&gt;. I saw this code snippet:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;App.ApplicationAdapter &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; DS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.JSONAPIAdapter.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;extend&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    namespace: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;v1&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using that gave me an error when &lt;code&gt;ember serve&lt;/code&gt;-ing, though:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;app.js: line 16, col 26, ‘DS’ is not defined.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Turns out, &lt;code&gt;DS&lt;/code&gt; isn’t in scope by default, even though &lt;code&gt;ember-cli&lt;/code&gt; installs Ember Data by default.&lt;/p&gt;
&lt;p&gt;Fixing this just means importing it at the top of &lt;code&gt;app/app.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; DS &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;ember-data&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Easy enough!&lt;/p&gt;</content:encoded></item><item><title>Resque 1.25.0 has been released</title><link>https://steveklabnik.com/writing/resque-1-25-0-has-been-released/</link><guid isPermaLink="true">https://steveklabnik.com/writing/resque-1-25-0-has-been-released/</guid><description>I’ve just released Resque 1.25.0! Resque is the most stable, widely-used job queue for Ruby. It uses Redis as its backing store. This release is thanks to adelcambre , who took the time to get it over the finish line! &amp;#x3C;3. A total of 19 contributors helped out with this…</description><pubDate>Mon, 16 Sep 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’ve just released Resque 1.25.0! Resque is the most stable, widely-used job queue for Ruby. It uses Redis as its backing store.&lt;/p&gt;
&lt;p&gt;This release is thanks to &lt;a href=&quot;https://github.com/adelcambre&quot;&gt;adelcambre&lt;/a&gt;, who took the time to get it over the finish line! &amp;#x3C;3.&lt;/p&gt;
&lt;p&gt;A total of 19 contributors helped out with this release, with 77 commits. Thank you to everyone!&lt;/p&gt;
&lt;p&gt;This release contains no changes from the 1.25.0.pre release that was put out a few weeks ago, so if you’re using it, you can upgrade with no problems.&lt;/p&gt;
&lt;h2 id=&quot;changes&quot;&gt;CHANGES&lt;/h2&gt;
&lt;p&gt;You can see the full CHANGELOG &lt;a href=&quot;https://github.com/resque/resque/blob/v1.25.0/HISTORY.md&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This release had a pre-release because of one big change: &lt;a href=&quot;https://github.com/resque/resque/pull/1017/files&quot;&gt;a refactor to the forking code&lt;/a&gt;. This was introduced to fix a problem: the exit syscall raises a SystemExit Exception in ruby, its exit is treated as a failure, thus deregistering the worker. After the refactor + fix, things should be peachy. But please give the prerelease a try.&lt;/p&gt;
&lt;p&gt;In addition, it has been discovered that we have accidentally introduced a SemVer violation back in v1.23.1: &lt;a href=&quot;https://github.com/resque/resque/issues/1074&quot;&gt;https://github.com/resque/resque/issues/1074&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I take SemVer seriously, and apologize for this change. SemVer states that at this time, I should basically do whatever. Since this fixes a bug, I’m inclined to leave it in. If this introduces a significant problem for you, please let me know. Since others might now be relying on this new behavior, I’m not 100% sure what the best option is. Your feedback helps.&lt;/p&gt;
&lt;h2 id=&quot;installing&quot;&gt;INSTALLING&lt;/h2&gt;
&lt;p&gt;To get 1.25.0 installed, just use &lt;code&gt;gem install&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ gem install resque&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or include it in your &lt;code&gt;Gemfile&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;gem &apos;resque&apos;, &apos;~&gt; 1.25.0&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;source&quot;&gt;SOURCE&lt;/h2&gt;
&lt;p&gt;You can find the source &lt;a href=&quot;https://github.com/resque/resque&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Beware subclassing Ruby core classes</title><link>https://steveklabnik.com/writing/beware-subclassing-ruby-core-classes/</link><guid isPermaLink="true">https://steveklabnik.com/writing/beware-subclassing-ruby-core-classes/</guid><description>TL;DR: Subclassing core classes in Ruby can lead to unexpected side effects. I suggest composition over inheritance in all these cases. Subclassing Review If you’re familiar with the concept of subclassing, skip down to “The Problem.” In Ruby, you can make your own classes: class…</description><pubDate>Wed, 24 Jul 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;TL;DR: Subclassing core classes in Ruby can lead to unexpected side effects. I suggest composition over inheritance in all these cases.&lt;/p&gt;
&lt;h2 id=&quot;subclassing-review&quot;&gt;Subclassing Review&lt;/h2&gt;
&lt;p&gt;If you’re familiar with the concept of subclassing, skip down to “The Problem.”&lt;/p&gt;
&lt;p&gt;In Ruby, you can make your own classes:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; List&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also make subclasses of those classes:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; OrderedList&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;List&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;puts&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; OrderedList&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kind_of?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# =&gt; true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, subclassing represents an “is a” relationship. This means that our &lt;code&gt;OrderedList&lt;/code&gt; should be a &lt;code&gt;List&lt;/code&gt; in every respect, but with some added behavior. The &lt;a href=&quot;http://en.wikipedia.org/wiki/Liskov_substitution_principle&quot;&gt;Liskov Substitution Principle&lt;/a&gt; is one formulation of this idea.&lt;/p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;
&lt;p&gt;Ruby has two major bits of code that it provides for your use: the core library and the standard library. &lt;a href=&quot;http://www.ruby-doc.org/core-2.0/&quot;&gt;The core library can be found here&lt;/a&gt;, and contains cllasses that you know and love, like &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;Hash&lt;/code&gt;, and &lt;code&gt;Array&lt;/code&gt;. &lt;a href=&quot;http://www.ruby-doc.org/stdlib-2.0/&quot;&gt;The standard library can be found here&lt;/a&gt;, and contains your favorite hits, like &lt;code&gt;CSV&lt;/code&gt;, &lt;code&gt;JSON&lt;/code&gt;, and &lt;code&gt;Logger&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;One way to think about the difference between core and the standard library is that core is written in C, while the standard library is written in Ruby. Core are the classes that are used the most, so they’re implemented in as low-level a fashion as possible. They’ll be in every single Ruby program, so might as well make them fast! The standard library only gets pulled in by bits and pieces; another way of thinking about the difference is that you need to &lt;code&gt;require&lt;/code&gt; everything in the standard library, but nothing in core.&lt;/p&gt;
&lt;p&gt;What do you think this code should do?&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Array&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;puts&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;to_a&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;class&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you said “it prints &lt;code&gt;Array&lt;/code&gt;,” you’d be right. This behavior really confuses me, though, because &lt;code&gt;List&lt;/code&gt; is already an &lt;code&gt;Array&lt;/code&gt;; in my mind, this operation shouldn’t suddenly change the class.&lt;/p&gt;
&lt;p&gt;Why does this happen? Let’s check out the implementation of &lt;a href=&quot;https://github.com/ruby/ruby/blob/trunk/array.c#L2064-L2082&quot;&gt;Array#to_a&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; VALUE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;rb_ary_to_a&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(VALUE &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ary&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;rb_obj_class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ary) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rb_cArray) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        VALUE dup &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; rb_ary_new2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;RARRAY_LEN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ary));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        rb_ary_replace&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(dup, ary);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; dup;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ary;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the class is not an &lt;code&gt;Array&lt;/code&gt;, (represented by &lt;code&gt;rb_cArray&lt;/code&gt;), then we make a new array of the same length, call &lt;code&gt;replace&lt;/code&gt; on it, and then return the new array. If this C scares you, here’s a direct port to pure Ruby:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; array_to_a&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ary)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ary.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Array&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    dup&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    dup.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;replace&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ary)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; dup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ary&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;array_to_a&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; # =&gt; Array&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So why do this? Well, again, this class will be used all over the place. For example, I made a brand new Rails 4 application, generated a controller and view, and put this in it:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;ObjectSpace&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;count_objects&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:T_ARRAY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;%=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; ObjectSpace&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;count_objects&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:T_ARRAY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;%&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ObjectSpace allows you to inspect all of the objects that exist in the system. Here’s the output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/PVwdvyY.png&quot; alt=&quot;http://i.imgur.com/PVwdvyY.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;rails arrays&lt;/p&gt;
&lt;p&gt;That’s a lot of arrays! This kind of shortcut is generally worth it: 99.99% of the time, this code is perfect.&lt;/p&gt;
&lt;p&gt;That last 0.01% is the problem. If you don’t know exactly how these classes operate at the C level, you’re gonna have a bad time. In this case, this behavior is odd enough that someone was kind enough to document it.&lt;/p&gt;
&lt;p&gt;Here’s the Ruby version of what I’d expect to happen:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; array_to_a2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ary)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ary.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;is_a?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Array&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  dup&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  dup.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;replace&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ary)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  dup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;array_to_a2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; # =&gt; List&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This has the exact same behavior except when we’re already dealing with an Array, which is what I’d expect.&lt;/p&gt;
&lt;p&gt;Let’s take another example: reverse.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;l&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;l &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;l &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;puts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; l.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;reverse&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; # =&gt; Array&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I would not expect that calling &lt;code&gt;#reverse&lt;/code&gt; on my custom &lt;code&gt;Array&lt;/code&gt; would change its class. Let’s &lt;a href=&quot;https://github.com/ruby/ruby/blob/trunk/array.c#L2138-L2161&quot;&gt;look at the C&lt;/a&gt; again:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; VALUE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;rb_ary_reverse_m&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(VALUE &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ary&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    long&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; len &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; RARRAY_LEN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ary);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    VALUE dup &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; rb_ary_new2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(len);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (len &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; VALUE &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;p1 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; RARRAY_RAWPTR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ary);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        VALUE &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;p2 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (VALUE &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;RARRAY_RAWPTR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(dup) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; len &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        do&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;p2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;p1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;len &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    ARY_SET_LEN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(dup, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;RARRAY_LEN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ary));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; dup;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We get the length of the array, make a new blank array of the same length, then do some pointer stuff to copy everything over, and return the new copy. Unlike &lt;code&gt;#to_a&lt;/code&gt;, this behavior is &lt;em&gt;not&lt;/em&gt; currently documented.&lt;/p&gt;
&lt;p&gt;Now: you could make the case that this behavior is expected, in both cases: after all, the point of the non-bang methods is to make a copy. However, there’s a difference to me between “make a new array with this stuff in it” and “make a new copy with this stuff in it”. Most of the time, I get the same class back, so I expect the same class back in these circumstances.&lt;/p&gt;
&lt;p&gt;Let’s talk about a more pernicious issue: Strings.&lt;/p&gt;
&lt;p&gt;As you know, the difference between interpolation and concatenation is that interpolation calls &lt;code&gt;#to_s&lt;/code&gt; implicitly on the object it’s interpolating:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;irb(main):001:0&gt; &quot;foo&quot; + 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;TypeError: no implicit conversion of Fixnum into String&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    from (irb):1:in `+&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    from (irb):1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    from /opt/rubies/ruby-2.0.0-p195/bin/irb:12:in `&amp;#x3C;main&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;irb(main):002:0&gt; &quot;foo#{2}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;=&gt; &quot;foo2&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;irb(main):001:0&gt; class MyClass&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;irb(main):002:1&gt; def to_s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;irb(main):003:2&gt; &quot;yup&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;irb(main):004:2&gt; end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;irb(main):005:1&gt; end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;=&gt; nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;irb(main):006:0&gt; &quot;foo#{MyClass.new}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;=&gt; &quot;fooyup&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So what about a custom &lt;code&gt;String&lt;/code&gt;?&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; MyString&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; to_s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;lol&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; MyString&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;concat&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Hey&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;puts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;puts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; s.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;to_s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;puts&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{s}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What does this print?&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ ruby ~/tmp/tmp.rb HeylolHey&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That’s right! With &lt;code&gt;String&lt;/code&gt;s, Ruby doesn’t call &lt;code&gt;#to_s&lt;/code&gt;: it puts the value in directly. How does this happen?&lt;/p&gt;
&lt;p&gt;Well, dealing with string interpolation deals with the parser, so let’s check out the bytecode that Ruby generates. Thanks to &lt;a href=&quot;http://twitter.com/tenderlove&quot;&gt;Aaron Patterson&lt;/a&gt; for suggesting this approach. &amp;#x3C;3&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;irb(main):013:0&gt; x = RubyVM::InstructionSequence.new(%q{puts &quot;hello #{&apos;hey&apos;}&quot;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;=&gt; &amp;#x3C;RubyVM::InstructionSequence:&amp;#x3C;compiled&gt;@&amp;#x3C;compiled&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;irb(main):014:0&gt; puts x.disasm&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;== disasm: &amp;#x3C;RubyVM::InstructionSequence:&amp;#x3C;compiled&gt;@&amp;#x3C;compiled&gt;&gt;==========&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0000 trace            1                                               (   1)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0002 putself&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0003 putstring        &quot;hello hey&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0005 opt_send_simple  &amp;#x3C;callinfo!mid:puts, argc:1, FCALL|ARGS_SKIP&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0007 leave&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;=&gt; nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;irb(main):015:0&gt; x = RubyVM::InstructionSequence.new(%q{puts &quot;hello #{Object.new}&quot;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;=&gt; &amp;#x3C;RubyVM::InstructionSequence:&amp;#x3C;compiled&gt;@&amp;#x3C;compiled&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;irb(main):016:0&gt; puts x.disasm&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;== disasm: &amp;#x3C;RubyVM::InstructionSequence:&amp;#x3C;compiled&gt;@&amp;#x3C;compiled&gt;&gt;==========&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0000 trace            1                                               (   1)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0002 putself&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0003 putobject        &quot;hello &quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0005 getinlinecache   12, &amp;#x3C;ic:0&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0008 getconstant      :Object&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0010 setinlinecache   &amp;#x3C;ic:0&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0012 opt_send_simple  &amp;#x3C;callinfo!mid:new, argc:0, ARGS_SKIP&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0014 tostring&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0015 concatstrings    2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0017 opt_send_simple  &amp;#x3C;callinfo!mid:puts, argc:1, FCALL|ARGS_SKIP&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0019 leave&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;=&gt; nil&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can see with a string, the bytecode actually puts the final concatenated string. But with an object. it ends up calling &lt;code&gt;tostring&lt;/code&gt;, and then &lt;code&gt;concatstrings&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Again, 99% of the time, this is totally fine, and much faster. But if you don’t know this trivia, you’re going to get bit.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://rails.lighthouseapp.com/projects/8994/tickets/6023-unable-to-find-by-subclasses-of-string-in-activerecord#ticket-6023-5&quot;&gt;Here&lt;/a&gt; is an example from an older version of Rails. Yes, you might think “Hey idiot, there’s no way it will store your custom &lt;code&gt;String&lt;/code&gt; class,” but the whole idea of subclassing is that it’s a drop-in replacement.&lt;/p&gt;
&lt;p&gt;I know that there’s some case where Ruby will not call your own implementation of &lt;code&gt;#initialize&lt;/code&gt; on a custom subclass of &lt;code&gt;String&lt;/code&gt;, but I can’t find it right now. This is why this problem is so tricky: most of the time, things are fine, but then occasionally, something strange happens and you wonder what’s wrong. I don’t know about you, but my brain needs to focus on more important things than the details of the implementation.&lt;/p&gt;
&lt;p&gt;Since I first wrote this post, &lt;a href=&quot;http://twitter.com/jeg2&quot;&gt;James Edward Gray II&lt;/a&gt; helped me remember what this example is. One of the early exercises in &lt;a href=&quot;http://exercism.io/&quot;&gt;http://exercism.io/&lt;/a&gt; is based on making a DNA type, and then doing some substitution operations on it. Many people inherited from &lt;code&gt;String&lt;/code&gt; when doing their answers, and while the simple case that passes the tests works, this case won’t:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Dna&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    super&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    puts&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Building Dna:  &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{inspect}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;result&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Dna&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;CATG&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;tr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Dna&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;T&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Dna&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;U&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; result.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;class&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; result&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This prints:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Building Dna:  &quot;CATG&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Building Dna:  &quot;T&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Building Dna:  &quot;U&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Dna&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;CAUG&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It never called our initializer for the new string. Let’s check &lt;a href=&quot;https://github.com/ruby/ruby/blob/trunk/string.c#L5484-L5525&quot;&gt;the source of &lt;code&gt;#tr&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; VALUE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;rb_str_tr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(VALUE &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, VALUE &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;src&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, VALUE &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;repl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    str &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; rb_str_dup&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(str);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    tr_trans&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(str, src, repl, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; str;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;rb_str_dup&lt;/code&gt; has a pretty simple definition:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;VALUE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;rb_str_dup&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(VALUE &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; str_duplicate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;rb_obj_class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(str), str);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and so does &lt;code&gt;str_duplicate&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; VALUE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;str_duplicate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(VALUE &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;klass&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, VALUE &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    VALUE dup &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; str_alloc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(klass);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    str_replace&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(dup, str);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; dup;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So there you have it: MRI doesn’t go through the whole initialization process when duplicating a string: it just allocates the memory and then replaces the contents.&lt;/p&gt;
&lt;p&gt;If you re-open &lt;code&gt;String&lt;/code&gt;, it’s also weird:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; String&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  alias_method&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; :string_initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:initialize&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;args, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;block)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    string_initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;args, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;block)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    puts&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Building MyString:  &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{inspect}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;result&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; String&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;CATG&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;tr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;T&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;U&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# =&gt; Building MyString: &quot;CATG&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; result.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; # =&gt; String&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; result &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# =&gt; &quot;CAUG&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again, unless you know exactly how this works at a low level, surprising things happen.&lt;/p&gt;
&lt;h2 id=&quot;the-solution&quot;&gt;The Solution&lt;/h2&gt;
&lt;p&gt;Generally speaking, subclassing isn’t the right idea here. You want a data structure that &lt;em&gt;uses&lt;/em&gt; one of these core classes internally, but isn’t exactly like one. Rather than this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;do this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;delegate&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;SimpleDelegator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    super&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This allows you to do the same thing, but without all of the pain:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; to_s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;hey&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; # =&gt; &quot;hey&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, this won’t solve all problems:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;delegate&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;SimpleDelegator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    super&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;([])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;l&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;l &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;l &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;puts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; l.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;reverse&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; # =&gt; Array&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In general, I’d prefer to delegate things manually, anyway: a &lt;code&gt;Name&lt;/code&gt; is not actually a drop-in for a &lt;code&gt;String&lt;/code&gt; it’s something different that happens to be a lot like one:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; List&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(list &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @list &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(item)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @list &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; item&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; reverse&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    List&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(@list.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;reverse&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;l&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;l &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;l &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;puts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; l.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;reverse&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  # =&gt; List&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can clean this up by using &lt;code&gt;Forwardable&lt;/code&gt; to only forward the messages you want to forward:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;forwardable&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; List&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  extend&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Forwardable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  def_delegators &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:@list&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:length&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; # and anything else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(list &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @list &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; reverse&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    List&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(@list.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;reverse&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;l&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;l &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;l &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;puts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; l.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;reverse&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; # =&gt; List&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you know! Be careful out there!&lt;/p&gt;</content:encoded></item><item><title>Resque 1.25.0.pre has been released</title><link>https://steveklabnik.com/writing/resque-1-25-0-pre-has-been-released/</link><guid isPermaLink="true">https://steveklabnik.com/writing/resque-1-25-0-pre-has-been-released/</guid><description>I’ve just released Resque 1.25.0.pre! Resque is the most stable, widely-used job queue for Ruby. It uses Redis as its backing store. This release is thanks to adelcambre , who took the time to get it over the finish line! &amp;#x3C;3 A total of 19 contributors helped out with this…</description><pubDate>Tue, 23 Jul 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’ve just released Resque 1.25.0.pre! Resque is the most stable, widely-used job queue for Ruby. It uses Redis as its backing store.&lt;/p&gt;
&lt;p&gt;This release is thanks to &lt;a href=&quot;https://github.com/adelcambre&quot;&gt;adelcambre&lt;/a&gt;, who took the time to get it over the finish line! &amp;#x3C;3&lt;/p&gt;
&lt;p&gt;A total of 19 contributors helped out with this release, with 77 commits. Thank you to everyone!&lt;/p&gt;
&lt;h2 id=&quot;changes&quot;&gt;CHANGES&lt;/h2&gt;
&lt;p&gt;You can see the full CHANGELOG &lt;a href=&quot;https://github.com/resque/resque/blob/v1.25.0.pre/HISTORY.md&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I am releasing this version as ‘pre’ due to one big change: &lt;a href=&quot;https://github.com/resque/resque/pull/1017/files&quot;&gt;a refactor to the forking code&lt;/a&gt;. This was introduced to fix a problem: the exit syscall raises a SystemExit Exception in ruby, its exit is treated as a failure, thus deregistering the worker. After the refactor + fix, things should be peachy. But please give the prerelease a try.&lt;/p&gt;
&lt;p&gt;In addition, it has been discovered that we have accidentally introduced a SemVer violation back in v1.23.1: &lt;a href=&quot;https://github.com/resque/resque/issues/1074&quot;&gt;https://github.com/resque/resque/issues/1074&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I take SemVer seriously, and apologize for this change. SemVer states that at this time, I should basically do whatever. Since this fixes a bug, I’m inclined to leave it in. If this introduces a significant problem for you, please let me know. Since others might now be relying on this new behavior, I’m not 100% sure what the best option is. Your feedback helps.&lt;/p&gt;
&lt;h2 id=&quot;installing&quot;&gt;INSTALLING&lt;/h2&gt;
&lt;p&gt;To get 1.25.0.pre installed, just use &lt;code&gt;gem install&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ gem install resque --pre&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;source&quot;&gt;SOURCE&lt;/h2&gt;
&lt;p&gt;You can find the source &lt;a href=&quot;https://github.com/resque/resque&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Removing Turbolinks from Rails 4</title><link>https://steveklabnik.com/writing/removing-turbolinks-from-rails-4/</link><guid isPermaLink="true">https://steveklabnik.com/writing/removing-turbolinks-from-rails-4/</guid><description>If you don’t want to use Turbolinks with your Rails 4 application, it’s easy! Just do this: Remove the gem &apos;turbolinks&apos; line from your Gemfile. Remove the //= require turbolinks from your app/assets/javascripts/application.js . Remove the two &quot;data-turbolinks-track&quot; =&gt; true hash…</description><pubDate>Tue, 25 Jun 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you don’t want to use Turbolinks with your Rails 4 application, it’s easy! Just do this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Remove the &lt;code&gt;gem &apos;turbolinks&apos;&lt;/code&gt; line from your Gemfile.&lt;/li&gt;
&lt;li&gt;Remove the &lt;code&gt;//= require turbolinks&lt;/code&gt; from your &lt;code&gt;app/assets/javascripts/application.js&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Remove the two &lt;code&gt;&quot;data-turbolinks-track&quot; =&gt; true&lt;/code&gt; hash key/value pairs from your &lt;code&gt;app/views/layouts/application.html.erb&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Done!&lt;/p&gt;</content:encoded></item><item><title>Rails 4.0.0-beta1 to Rails 4.0.0-rc1</title><link>https://steveklabnik.com/writing/rails-4-0-0-beta1-to-rails-4-0-0-rc1/</link><guid isPermaLink="true">https://steveklabnik.com/writing/rails-4-0-0-beta1-to-rails-4-0-0-rc1/</guid><description>I’m writing Rails 4 in Action along with Ryan Bigg and Yehuda Katz. In updating the book to Rails 4, I started early: the sample app ( ticketee ) was done with 4.0.0.beta1 . Then 4.0.0.rc1 came out. I didn’t upgrade immediately, but last night, I took the plunge. There were only…</description><pubDate>Tue, 21 May 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’m writing &lt;a href=&quot;http://www.manning.com/bigg2/&quot;&gt;Rails 4 in Action&lt;/a&gt; along with Ryan Bigg and Yehuda Katz. In updating the book to Rails 4, I started early: the sample app (&lt;a href=&quot;https://github.com/steveklabnik/ticketee&quot;&gt;ticketee&lt;/a&gt;) was done with &lt;code&gt;4.0.0.beta1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then &lt;code&gt;4.0.0.rc1&lt;/code&gt; came out. I didn’t upgrade immediately, but last night, I took the plunge. There were only three errors, and the whole process took me something like 40 minutes.&lt;/p&gt;
&lt;p&gt;Here’s what I had to do:&lt;/p&gt;
&lt;h2 id=&quot;cookie-stores&quot;&gt;Cookie Stores&lt;/h2&gt;
&lt;p&gt;Error:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;/Users/steve/.gem/ruby/2.0.0/gems/railties-4.0.0.rc1/lib/rails/application/configuration.rb:144:in `const_get&apos;: uninitialized constant ActionDispatch::Session::EncryptedCookieStore (NameError)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The EncryptedCookieStore went away. Now, the regular cookie store handles these kinds of things.&lt;/p&gt;
&lt;p&gt;Fix:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rbindex c512cda..b4681fd 100644--- a/config/initializers/session_store.rb+++ b/config/initializers/session_store.rb@@ -1,3 +1,3 @@ # Be sure to restart your server when you modify this file.-Ticketee::Application.config.session_store :encrypted_cookie_store, key: &apos;_ticketee_session&apos;+Ticketee::Application.config.session_store :cookie_store, key: &apos;_ticketee_session&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;routes&quot;&gt;Routes&lt;/h2&gt;
&lt;p&gt;Error:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;/Users/steve/.gem/ruby/2.0.0/gems/actionpack-4.0.0.rc1/lib/action_dispatch/routing/route_set.rb:408:in `add_route&apos;: Invalid route name, already in use: &apos;signin&apos;  (ArgumentError)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;You may have defined two routes with the same name using the `:as` option, or you may be overriding a route already defined by a resource with the same naming. For the latter, you can restrict the routes created with `resources` as explained here:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;http://guides.rubyonrails.org/routing.html#restricting-the-routes-created&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can’t name two routes the same thing any more. In my case, just dropping the &lt;code&gt;:as&lt;/code&gt; allowed me to get to where I needed to go:&lt;/p&gt;
&lt;p&gt;Fix:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;diff --git a/config/routes.rb b/config/routes.rbindex f010adb..d573e89 100644--- a/config/routes.rb+++ b/config/routes.rb@@ -2,8 +2,8 @@ Ticketee::Application.routes.draw do   root to: &quot;projects#index&quot;-  get &quot;/signin&quot;, to: &quot;sessions#new&quot;, as: &quot;signin&quot;-  post &quot;/signin&quot;, to: &quot;sessions#create&quot;, as: &quot;signin&quot;+  get &quot;/signin&quot;, to: &quot;sessions#new&quot;+  post &quot;/signin&quot;, to: &quot;sessions#create&quot;   delete &quot;/signout&quot;, to: &quot;sessions#destroy&quot;, as: &quot;signout&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;clean-dbs&quot;&gt;Clean dbs&lt;/h2&gt;
&lt;p&gt;Error:&lt;/p&gt;
&lt;p&gt;Tons of test failures relating to what was essentially “I don’t delete the db between test runs.”&lt;/p&gt;
&lt;p&gt;Fix:&lt;/p&gt;
&lt;p&gt;Upgrade to rspec-rails 2.13.2. Done!&lt;/p&gt;
&lt;h2 id=&quot;has_secure_password&quot;&gt;has_secure_password&lt;/h2&gt;
&lt;p&gt;Error:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  1) User passwords needs a password and confirmation to save&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     Failure/Error: expect(u).to_not be_valid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       expected #&amp;#x3C;User id: 1, name: &quot;steve&quot;, email: &quot;steve@example.com&quot;, password_digest: &quot;$2a$04$9D7M2iPvYavvvpb3rlLzz.vqMJdGBAQVBSJ6L.UIoXP6...&quot;, created_at: &quot;2013-05-21 23:59:44&quot;, updated_at: &quot;2013-05-21 23:59:44&quot;, admin: false&gt; not to be valid&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This test failed. The test looked like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;it &quot;needs a password and confirmation to save&quot; do  u = User.new(name: &quot;steve&quot;, email: &quot;steve@example.com&quot;)  u.save  expect(u).to_not be_valid  u.password = &quot;password&quot;  u.password_confirmation = &quot;&quot;  u.save  expect(u).to_not be_valid  u.password_confirmation = &quot;password&quot;  u.save  expect(u).to be_validend&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Turns out, &lt;a href=&quot;https://github.com/rails/rails/pull/10694&quot;&gt;it’s a regression&lt;/a&gt;! This will get fixed for RC2, but for now, just commenting out that middle section works. The final test is good enough for now.&lt;/p&gt;</content:encoded></item><item><title>Travis build matrix for Rails</title><link>https://steveklabnik.com/writing/travis-build-matrix-for-rails/</link><guid isPermaLink="true">https://steveklabnik.com/writing/travis-build-matrix-for-rails/</guid><description>Do you have a gem that needs to test against multiple versions of Rails? Doing it all can be complex, and while I have lots to say about this topic, but here’s one of the pieces: Travis build matrix. Here’s what you want: language : ruby rvm : - 1.8.7 - 1.9.2 - 1.9.3 - 2.0.0 -…</description><pubDate>Sun, 10 Mar 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Do you have a gem that needs to test against multiple versions of Rails? Doing it all can be complex, and while I have lots to say about this topic, but here’s one of the pieces: Travis build matrix.&lt;/p&gt;
&lt;p&gt;Here’s what you want:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;language&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;ruby&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;rvm&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  - &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.8.7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  - &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.9.2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  - &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.9.3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  - &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2.0.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;ruby-head&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;RAILS_VERSION=3.2&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;RAILS_VERSION=3.1&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;RAILS_VERSION=3.0&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;RAILS_VERSION=master&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;matrix&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  allow_failures&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;rvm&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;ruby-head&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;RAILS_VERSION=master&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  exclude&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;rvm&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2.0.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      env&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;RAILS_VERSION=3.0&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;rvm&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2.0.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      env&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;RAILS_VERSION=3.1&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;rvm&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.8.7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      env&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;RAILS_VERSION=master&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;rvm&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.9.2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      env&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;RAILS_VERSION=master&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;rvm&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;ruby-head&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      env&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;RAILS_VERSION=3.0&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;rvm&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;ruby-head&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      env&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;RAILS_VERSION=3.1&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here’s what all this does:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;1.8.7 and 1.9.2 is supported across all of the 3.x series, but not master&lt;/li&gt;
&lt;li&gt;2.0.0 is supported on Rails 3.2 (as of the upcoming 3.2.13, but it will probably work with your gem with 3.2.12) and master, but not 3.0 or 3.1.&lt;/li&gt;
&lt;li&gt;We want to allow failures on ruby-head, because it’s not likely to be stable&lt;/li&gt;
&lt;li&gt;We also want to allow failures for Rails master, because sometimes it’s not stable either&lt;/li&gt;
&lt;li&gt;ruby-head should only be built against master&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;What do you think? &lt;a href=&quot;http://twitter.com/steveklabnik&quot;&gt;Tweet at me&lt;/a&gt; if you have suggestions for improving this matrix.&lt;/p&gt;</content:encoded></item><item><title>Using puma on Heroku</title><link>https://steveklabnik.com/writing/using-puma-on-heroku/</link><guid isPermaLink="true">https://steveklabnik.com/writing/using-puma-on-heroku/</guid><description>I’m a big fan of Puma these days. Today, I converted my blog over to use Puma, and I figured I’d share how I did it. This blog uses Sinatra. If you want to look ahead, here is the commit. Gemfile Installing Puma is really easy: just add gem &apos;puma&apos; to your Gemfile. Done! This…</description><pubDate>Sun, 24 Feb 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’m a big fan of &lt;a href=&quot;http://puma.io/&quot;&gt;Puma&lt;/a&gt; these days. Today, I converted my blog over to use Puma, and I figured I’d share how I did it. This blog uses Sinatra.&lt;/p&gt;
&lt;p&gt;If you want to look ahead, &lt;a href=&quot;https://github.com/steveklabnik/blog/commit/3cd0f04ed29a25df6d6dfeeffccd2e12548c05cf&quot;&gt;here&lt;/a&gt; is the commit.&lt;/p&gt;
&lt;h2 id=&quot;gemfile&quot;&gt;Gemfile&lt;/h2&gt;
&lt;p&gt;Installing Puma is really easy: just add &lt;code&gt;gem &apos;puma&apos;&lt;/code&gt; to your Gemfile. Done!&lt;/p&gt;
&lt;p&gt;This section is way too easy. I’m sorry Puma isn’t more complicated. ;)&lt;/p&gt;
&lt;h2 id=&quot;procfile&quot;&gt;Procfile&lt;/h2&gt;
&lt;p&gt;Heroku attempts to guess how you want to run your site, but sometimes it guesses wrong. I prefer to be a bit more explicit, and in Puma’s case, it will guess wrong and use Webrick, so we need to do this step.&lt;/p&gt;
&lt;p&gt;Heroku uses a gem called &lt;code&gt;foreman&lt;/code&gt; to run your application. Basically, &lt;code&gt;foreman&lt;/code&gt; gives you a ‘Procfile’ that lets you specify different processes and their types, and then foreman manages running them for you.&lt;/p&gt;
&lt;p&gt;To use &lt;code&gt;foreman&lt;/code&gt;, add it to your Gemfile:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;gem &apos;foreman&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then make a &lt;code&gt;Procfile&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;web: rackup -s puma -p $PORT&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This says “I want my web processes to run this command.” Simple. We tell &lt;code&gt;rackup&lt;/code&gt; to use Puma with the &lt;code&gt;-s&lt;/code&gt; flag, for ‘server.’&lt;/p&gt;
&lt;p&gt;To start up your application, normall you’d run &lt;code&gt;rackup&lt;/code&gt; yourself, but now, you use &lt;code&gt;foreman&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ bundle exec foreman start&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’ll print out a bunch of messages. Mine looks like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ bundle exec foreman start&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;15:05:05 web.1  | started with pid 52450&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;15:05:06 web.1  | Puma 1.6.3 starting...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;15:05:06 web.1  | * Min threads: 0, max threads: 16&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;15:05:06 web.1  | * Environment: development&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;15:05:06 web.1  | * Listening on tcp://0.0.0.0:5000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you can &lt;code&gt;open http://localhost:5000&lt;/code&gt; in another terminal, and bam! Done.&lt;/p&gt;
&lt;h2 id=&quot;other-rubies&quot;&gt;Other Rubies&lt;/h2&gt;
&lt;p&gt;If you really want Puma to scream, you should run with Rubinius or JRuby. I haven’t done this yet, but once I do, I’ll update this post with instructions.&lt;/p&gt;
&lt;h2 id=&quot;rails&quot;&gt;Rails&lt;/h2&gt;
&lt;p&gt;If you’re using Rails, it’s the same process, but the Procfile line should be&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;web: bundle exec puma -p $PORT&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Easy!&lt;/p&gt;</content:encoded></item><item><title>I&apos;m writing &quot;Rails 4 in Action&quot;!</title><link>https://steveklabnik.com/writing/i-m-writing--rails-4-in-action--/</link><guid isPermaLink="true">https://steveklabnik.com/writing/i-m-writing--rails-4-in-action--/</guid><description>Last night, I took a big step forward in my writing career: I’ll be building upon the work Ryan Bigg was doing to take “Rails 3 in Action” and move it to Rails 4. I signed the contract a few weeks ago, but last night I actually did the first bit of editing, and successfully got…</description><pubDate>Wed, 13 Feb 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Last night, I took a big step forward in my writing career: I’ll be building upon the work Ryan Bigg was doing to take “Rails 3 in Action” and move it to Rails 4. I signed the contract a few weeks ago, but last night I actually did the first bit of editing, and successfully got everything through the system.&lt;/p&gt;
&lt;p&gt;Here’s the &lt;a href=&quot;http://www.manning.com/bigg2/&quot;&gt;early access edition&lt;/a&gt; link, where you can check out what I’m doing. Of course, Rails 4 isn’t actually out yet, but since I’m on the Rails team, I already keep abreast of changes daily. I’ll be doing a first pass to take the book from 3.2 to edge over the next few weeks, and then keeping it current until the actual release of Rails 4.&lt;/p&gt;
&lt;p&gt;Of course, updating the content is much easier than writing it in the first place. Thanks for all of your hard work on previous editions, Yehuda and Ryan!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Of course, this doesn’t mean I’ll stop working my my two self-published books, &lt;a href=&quot;http://www.designinghypermediaapis.com/&quot;&gt;Designing Hypermedia APIs&lt;/a&gt; and &lt;a href=&quot;http://www.rustforrubyists.com/&quot;&gt;Rust for Rubyists&lt;/a&gt;. It just means I’ll be doing even more writing!&lt;/p&gt;</content:encoded></item><item><title>Ruby on Rails maintenance policy</title><link>https://steveklabnik.com/writing/ruby-on-rails-maintenance-policy/</link><guid isPermaLink="true">https://steveklabnik.com/writing/ruby-on-rails-maintenance-policy/</guid><description>Recently, the Rails team has committed to a specific policy related to release maintenance. Due to the rapid pace of recent releases, it’s good to understand how your apps relate to this policy. The policy was originally posted on Google Groups, here:…</description><pubDate>Mon, 11 Feb 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Recently, the Rails team has committed to a specific policy related to release maintenance. Due to the rapid pace of recent releases, it’s good to understand how your apps relate to this policy.&lt;/p&gt;
&lt;p&gt;The policy was originally posted on Google Groups, here: &lt;a href=&quot;https://groups.google.com/forum/?fromgroups=#!topic/rubyonrails-security/G4TTUDDYbNA&quot;&gt;https://groups.google.com/forum/?fromgroups=#!topic/rubyonrails-security/G4TTUDDYbNA&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here’s a copy if you don’t want to read Google Groups:&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Since the most recent patch releases there has been some confusion about what versions of Ruby on Rails are currently supported, and when people can expect new versions. Our maintenance policy is as follows.&lt;/p&gt;
&lt;p&gt;Support of the Rails framework is divided into four groups: New features, bug fixes, security issues, and severe security issues. They are handled as follows:&lt;/p&gt;
&lt;h2 id=&quot;new-features&quot;&gt;New Features&lt;/h2&gt;
&lt;p&gt;New Features are only added to the master branch and will not be made available in point releases.&lt;/p&gt;
&lt;h2 id=&quot;bug-fixes&quot;&gt;Bug fixes&lt;/h2&gt;
&lt;p&gt;Only the latest release series will receive bug fixes. When enough bugs are fixed and its deemed worthy to release a new gem, this is the branch it happens from.&lt;/p&gt;
&lt;p&gt;Currently included series: 3.2.x&lt;/p&gt;
&lt;h2 id=&quot;security-issues&quot;&gt;Security issues:&lt;/h2&gt;
&lt;p&gt;The current release series and the next most recent one will receive patches and new versions in case of a security issue.&lt;/p&gt;
&lt;p&gt;Currently included series: 3.2.x, 3.1.x&lt;/p&gt;
&lt;h2 id=&quot;severe-security-issues&quot;&gt;Severe security issues:&lt;/h2&gt;
&lt;p&gt;For severe security issues we will provide new versions as above, and also the last major release series will receive patches and new versions. The classification of the security issue is judged by the core team.&lt;/p&gt;
&lt;p&gt;Currently included series: 3.2.x, 3.1.x, 2.3.x&lt;/p&gt;
&lt;h2 id=&quot;unsupported-release-series&quot;&gt;Unsupported Release Series&lt;/h2&gt;
&lt;p&gt;When a release series is no longer supported, it’s your own responsibility to deal with bugs and security issues. We may provide back-ports of the fixes and publish them to git, however there will be no new versions released. If you are not comfortable maintaining your own versions, you should upgrade to a supported version.&lt;/p&gt;
&lt;p&gt;You should also be aware that Ruby 1.8 will reach End of Life in June 2013, no further ruby security releases will be provided after that point. If your application is only compatible ruby 1.8 you should upgrade accordingly.&lt;/p&gt;
&lt;p&gt;– Cheers,&lt;/p&gt;
&lt;p&gt;Koz&lt;/p&gt;</content:encoded></item><item><title>Ember.js and accessibility</title><link>https://steveklabnik.com/writing/emberjs-and-accessibility/</link><guid isPermaLink="true">https://steveklabnik.com/writing/emberjs-and-accessibility/</guid><description>Hey everyone! I made a video today about Ember.js and accessibility. I had always been repeating what I’d heard about screen readers: they can’t work with JavaScript. Turns out that’s not exactly true. The video is the best way to show you: VoiceOver, Ember.js, and WAI-ARIA from…</description><pubDate>Thu, 07 Feb 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hey everyone! I made a video today about Ember.js and accessibility. I had always been repeating what I’d heard about screen readers: they can’t work with JavaScript. Turns out that’s not exactly true. The video is the best way to show you:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://vimeo.com/59124303&quot;&gt;VoiceOver, Ember.js, and WAI-ARIA&lt;/a&gt; from &lt;a href=&quot;http://vimeo.com/steveklabnik&quot;&gt;Steve Klabnik&lt;/a&gt; on &lt;a href=&quot;http://vimeo.com/&quot;&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here’s a rough transcript, if you don’t want to watch it:&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Hey everyone. I recently was checking out &lt;a href=&quot;http://emberjs.com/&quot;&gt;Ember.js&lt;/a&gt;, and more specifically, &lt;a href=&quot;http://discourse.org/&quot;&gt;Discourse&lt;/a&gt;. Discourse is supposed to be a next-generation discussion platform, and it’s an Ember app backed by a Rails-based JSON API. I mentioned to Ember co-creator &lt;a href=&quot;http://twitter.com/wycats&quot;&gt;Yehuda Katz&lt;/a&gt; that I wished Ember had ‘a better accessibility story’. He asked me to elaborate, and I mentioned how my friends on Twitter were saying that Discourse wouldn’t able to be inclusive because JavaScript-heavy apps can’t be used by screenreaders. So he said, “Hit ⌘-F5.”&lt;/p&gt;
&lt;p&gt;Whoah.&lt;/p&gt;
&lt;p&gt;Hitting that key combination activates &lt;a href=&quot;http://www.apple.com/accessibility/voiceover/&quot;&gt;VoiceOver&lt;/a&gt;, a feature of OS X I didn’t know existed. Basically, VoiceOver is able to interact with applications and allow keyboard navigation for those who are blind or sight-impaired. Neat! But what about in-browser? Turns out VoiceOver handles JavaScript heavy pages just fine.&lt;/p&gt;
&lt;p&gt;I tried it out on &lt;a href=&quot;http://try.discourse.org/&quot;&gt;http://try.discourse.org/&lt;/a&gt;, and it works pretty well! Not perfect, but you can manage. Yehuda also pointed me at &lt;a href=&quot;http://www.w3.org/WAI/intro/aria.php&quot;&gt;WAI-ARIA&lt;/a&gt;, which is a W3C initiative. I’ll let the site explain:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;WAI-ARIA, the Accessible Rich Internet Applications Suite, defines a way to make Web content and Web applications more accessible to people with disabilities. It especially helps with dynamic content and advanced user interface controls developed with Ajax, HTML, JavaScript, and related technologies.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Neat! Basically, you can add markup to your HTML, and it will help applications like VoiceOver allow people to use your site more easily, even if it uses a lot of Ajax. This is super cool, and for me, mitigates one of my main complaints against using SPAs. Of course, WAI-ARIA isn’t really Ember’s job; you’ll have to make the HTML be output in the right way yourself. But it makes me really happy to know that people with disabilities don’t need to be left out of the rich-client portion of the web.&lt;/p&gt;</content:encoded></item><item><title>How to not rely on rubygems.org for development</title><link>https://steveklabnik.com/writing/how-to-not-rely-on-rubygemsorg-for-deployment/</link><guid isPermaLink="true">https://steveklabnik.com/writing/how-to-not-rely-on-rubygemsorg-for-deployment/</guid><description>Due to the recent situation with Rubygems.org , a lot of people noticed that they rely on Rubygems.org when deploying. A lot of people advocate “vendor everything” , and while that’s one approach, I actually don’t think it’s necessary. I think a lot of people think they rely on…</description><pubDate>Thu, 31 Jan 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Due to the recent &lt;a href=&quot;https://status.heroku.com/incidents/489&quot;&gt;situation with Rubygems.org&lt;/a&gt;, a lot of people noticed that they rely on Rubygems.org when deploying. A lot of people advocate &lt;a href=&quot;http://ryan.mcgeary.org/2011/02/09/vendor-everything-still-applies/&quot;&gt;“vendor everything”&lt;/a&gt;, and while that’s one approach, I actually don’t think it’s necessary. I think a lot of people &lt;em&gt;think&lt;/em&gt; they rely on Rubygems.org more than they actually do, or, at least, aren’t deploying with Bundler correctly. So let’s talk about it.&lt;/p&gt;
&lt;h2 id=&quot;deploying-with-bundler&quot;&gt;Deploying with Bundler&lt;/h2&gt;
&lt;p&gt;Bundler has a &lt;code&gt;--deployment&lt;/code&gt; flag to help you deploy code. &lt;a href=&quot;http://gembundler.com/v1.2/deploying.html&quot;&gt;Here’s the documentation&lt;/a&gt;. If you use Bundler, and you don’t use &lt;code&gt;--deployment&lt;/code&gt; when deploying, you are probably Doing It Wrong. Let’s try a brand new app, and see what happens:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ rails _3.2.11_ new foo --skip-bundle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  README.rdoc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  Rakefile&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config.ru&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  .gitignore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  Gemfile&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  app/assets/images/rails.png&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  app/assets/javascripts/application.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  app/assets/stylesheets/application.css&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  app/controllers/application_controller.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  app/helpers/application_helper.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  app/views/layouts/application.html.erb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  app/mailers/.gitkeep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  app/models/.gitkeep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/routes.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/application.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/environment.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/environments&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/environments/development.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/environments/production.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/environments/test.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/initializers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/initializers/backtrace_silencers.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/initializers/inflections.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/initializers/mime_types.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/initializers/secret_token.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/initializers/session_store.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/initializers/wrap_parameters.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/locales&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/locales/en.yml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/boot.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  config/database.yml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  db/seeds.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  doc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  doc/README_FOR_APP&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  lib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  lib/tasks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  lib/tasks/.gitkeep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  lib/assets&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  lib/assets/.gitkeep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  log&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  log/.gitkeep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  public&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  public/404.html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  public/422.html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  public/500.html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  public/favicon.ico&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  public/index.html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  public/robots.txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  script&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  script/rails&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  test/fixtures&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  test/fixtures/.gitkeep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  test/functional&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  test/functional/.gitkeep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  test/integration&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  test/integration/.gitkeep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  test/unit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  test/unit/.gitkeep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  test/performance/browsing_test.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  test/test_helper.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  tmp/cache&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  tmp/cache/assets&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  vendor/assets/javascripts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  vendor/assets/javascripts/.gitkeep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  vendor/assets/stylesheets&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  vendor/assets/stylesheets/.gitkeep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  vendor/plugins&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  vendor/plugins/.gitkeep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ cd foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ cat .bundle/config &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;cat: .bundle/config: No such file or directory&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We have no configuration for bundler. Makes sense, we never bundled. If we try to use &lt;code&gt;--deployment&lt;/code&gt; now, we get an error:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;[1] $ bundle install --deployment                                             ✘&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;The --deployment flag requires a Gemfile.lock. Please make sure you have checked your Gemfile.lock into version control before deploying.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is because &lt;code&gt;--deployment&lt;/code&gt; checks the lock. So let’s make one:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;[16] $ bundle                                                                 ✘&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Fetching gem metadata from https://rubygems.org/...........&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Fetching gem metadata from https://rubygems.org/..&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rake (10.0.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using i18n (0.6.1) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using multi_json (1.5.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using activesupport (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using builder (3.0.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using activemodel (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using erubis (2.7.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using journey (1.0.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rack (1.4.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rack-cache (1.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rack-test (0.6.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using hike (1.2.1) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using tilt (1.3.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using sprockets (2.2.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using actionpack (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using mime-types (1.19) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using polyglot (0.3.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using treetop (1.4.12) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using mail (2.4.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using actionmailer (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using arel (3.0.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using tzinfo (0.3.35) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using activerecord (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using activeresource (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using bundler (1.3.0.pre.5) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using coffee-script-source (1.4.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using execjs (1.4.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using coffee-script (2.2.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing rack-ssl (1.3.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using json (1.7.6) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rdoc (3.12) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using thor (0.17.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using railties (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using coffee-rails (3.2.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using jquery-rails (2.2.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rails (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using sass (3.2.5) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using sass-rails (3.2.6) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using sqlite3 (1.3.7) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using uglifier (1.3.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This of course does hit the network, and does all the usual things. Your application normally has a lock already and has it checked in. We still don’t have a config:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ cat .bundle/config&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;cat: .bundle/config: No such file or directory&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, this is the state our app would be in before deploying. At this point, it’s just like we did a &lt;code&gt;git pull&lt;/code&gt; or an &lt;code&gt;scp&lt;/code&gt; to our server. So let’s install for deployment:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ bundle install --deployment&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Fetching gem metadata from https://rubygems.org/.........&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Fetching gem metadata from https://rubygems.org/..&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing rake (10.0.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing i18n (0.6.1) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing multi_json (1.5.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing activesupport (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing builder (3.0.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing activemodel (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing erubis (2.7.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing journey (1.0.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing rack (1.4.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing rack-cache (1.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing rack-test (0.6.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing hike (1.2.1) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing tilt (1.3.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing sprockets (2.2.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing actionpack (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing mime-types (1.19) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing polyglot (0.3.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing treetop (1.4.12) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing mail (2.4.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing actionmailer (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing arel (3.0.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing tzinfo (0.3.35) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing activerecord (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing activeresource (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing coffee-script-source (1.4.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing execjs (1.4.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing coffee-script (2.2.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing rack-ssl (1.3.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing json (1.7.6) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing rdoc (3.12) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing thor (0.17.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing railties (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing coffee-rails (3.2.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing jquery-rails (2.2.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using bundler (1.3.0.pre.5) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing rails (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing sass (3.2.5) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing sass-rails (3.2.6) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing sqlite3 (1.3.7) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing uglifier (1.3.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Your bundle is complete! It was installed into ./vendor/bundle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Post-install message from rdoc:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Depending on your version of ruby, you may need to install ruby rdoc/ri data:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;= 1.8.6 : unsupported&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; = 1.8.7 : gem install rdoc-data; rdoc-data --install&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; = 1.9.1 : gem install rdoc-data; rdoc-data --install&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt;= 1.9.2 : nothing to do! Yay!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We still hit Rubygems.org, but note now that it said “Installing” rather than using. That’s because we now have everything vendored:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ cat .bundle/config&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;BUNDLE_FROZEN: &apos;1&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;BUNDLE_PATH: vendor/bundle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;BUNDLE_DISABLE_SHARED_GEMS: &apos;1&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ ls vendor/bundle/ruby/1.9.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;bin            cache          doc            gems           specifications&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ ls vendor/bundle/ruby/1.9.1/gems&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;actionmailer-3.2.11        multi_json-1.5.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;actionpack-3.2.11          polyglot-0.3.3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;activemodel-3.2.11         rack-1.4.4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;activerecord-3.2.11        rack-cache-1.2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;activeresource-3.2.11      rack-ssl-1.3.3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;activesupport-3.2.11       rack-test-0.6.2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;arel-3.0.2                 rails-3.2.11&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;builder-3.0.4              railties-3.2.11&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;coffee-rails-3.2.2         rake-10.0.3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;coffee-script-2.2.0        rdoc-3.12&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;coffee-script-source-1.4.0 sass-3.2.5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;erubis-2.7.0               sass-rails-3.2.6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;execjs-1.4.0               sprockets-2.2.2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;hike-1.2.1                 sqlite3-1.3.7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;i18n-0.6.1                 thor-0.17.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;journey-1.0.4              tilt-1.3.3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;jquery-rails-2.2.0         treetop-1.4.12&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;json-1.7.6                 tzinfo-0.3.35&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;mail-2.4.4                 uglifier-1.3.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;mime-types-1.19&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Okay! Neat. So we’ve Vendored Everything… what happens if we &lt;code&gt;bundle&lt;/code&gt; again?&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ bundle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rake (10.0.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using i18n (0.6.1) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using multi_json (1.5.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using activesupport (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using builder (3.0.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using activemodel (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using erubis (2.7.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using journey (1.0.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rack (1.4.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rack-cache (1.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rack-test (0.6.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using hike (1.2.1) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using tilt (1.3.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using sprockets (2.2.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using actionpack (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using mime-types (1.19) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using polyglot (0.3.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using treetop (1.4.12) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using mail (2.4.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using actionmailer (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using arel (3.0.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using tzinfo (0.3.35) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using activerecord (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using activeresource (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using coffee-script-source (1.4.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using execjs (1.4.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using coffee-script (2.2.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rack-ssl (1.3.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using json (1.7.6) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rdoc (3.12) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using thor (0.17.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using railties (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using coffee-rails (3.2.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using jquery-rails (2.2.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using bundler (1.3.0.pre.5) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rails (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using sass (3.2.5) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using sass-rails (3.2.6) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using sqlite3 (1.3.7) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using uglifier (1.3.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Your bundle is complete! It was installed into ./vendor/bundle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;bundle&lt;/code&gt; command uses our config settings in &lt;code&gt;.bundle/config&lt;/code&gt;, which re-runs with the vendored bundle.&lt;/p&gt;
&lt;h2 id=&quot;wait-i-thought-you-said-no-to-vendor-everything&quot;&gt;Wait, I thought you said NO to Vendor Everything!!!&lt;/h2&gt;
&lt;p&gt;Well, here’s the deal: you can Vendor Everything &lt;em&gt;on your server&lt;/em&gt;, which means that we’re not committing gems into source control, and then pushing that huge mess over the network.&lt;/p&gt;
&lt;p&gt;Let’s re-examine &lt;code&gt;--deployment&lt;/code&gt; in the context of our two strategies: &lt;code&gt;scp&lt;/code&gt; and &lt;code&gt;git&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;git&quot;&gt;git&lt;/h3&gt;
&lt;p&gt;If you deploy with git, it’s two ways: &lt;code&gt;ssh&lt;/code&gt;ing into the server and running a &lt;code&gt;git pull&lt;/code&gt;, or by doing a &lt;code&gt;git push&lt;/code&gt;. In both cases, you’ll have some sort of post-deploy hook that manages the rest of the deploy.&lt;/p&gt;
&lt;p&gt;This scenario is exactly as shown above: just make sure that your first &lt;code&gt;bundle&lt;/code&gt; on deploy is using &lt;code&gt;--deployment&lt;/code&gt;, and you’re Good To Go. Each next deploy won’t hit the network. Rock on.&lt;/p&gt;
&lt;h3 id=&quot;scp&quot;&gt;scp&lt;/h3&gt;
&lt;p&gt;If you use scp in some way to deploy, then you’re getting a new copy of the application every time, so that bundle full of gems won’t work. You need one more flag: &lt;code&gt;--path&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ rm -rf vendor       &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ bundle install --deployment --path ../vendor/bundle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Fetching gem metadata from https://rubygems.org/.........&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Fetching gem metadata from https://rubygems.org/..&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing rake (10.0.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing i18n (0.6.1) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing multi_json (1.5.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing activesupport (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing builder (3.0.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing activemodel (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing erubis (2.7.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing journey (1.0.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing rack (1.4.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing rack-cache (1.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing rack-test (0.6.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing hike (1.2.1) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing tilt (1.3.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing sprockets (2.2.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing actionpack (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing mime-types (1.19) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing polyglot (0.3.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing treetop (1.4.12) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing mail (2.4.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing actionmailer (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing arel (3.0.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing tzinfo (0.3.35) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing activerecord (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing activeresource (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing coffee-script-source (1.4.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing execjs (1.4.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing coffee-script (2.2.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing rack-ssl (1.3.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing json (1.7.6) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing rdoc (3.12) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing thor (0.17.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing railties (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing coffee-rails (3.2.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing jquery-rails (2.2.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using bundler (1.3.0.pre.5) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing rails (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing sass (3.2.5) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing sass-rails (3.2.6) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing sqlite3 (1.3.7) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Installing uglifier (1.3.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Your bundle is complete! It was installed into /Users/steve/tmp/vendor/bundle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Post-install message from rdoc:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Depending on your version of ruby, you may need to install ruby rdoc/ri data:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;= 1.8.6 : unsupported&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; = 1.8.7 : gem install rdoc-data; rdoc-data --install&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; = 1.9.1 : gem install rdoc-data; rdoc-data --install&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt;= 1.9.2 : nothing to do! Yay!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ cat .bundle/config &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;BUNDLE_FROZEN: &apos;1&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;BUNDLE_PATH: ../vendor/bundle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;BUNDLE_DISABLE_SHARED_GEMS: &apos;1&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ ls vendor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ls: vendor: No such file or directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;[1] $ ls ../vendor                                                            ✘&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;bundle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ bundle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rake (10.0.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using i18n (0.6.1) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using multi_json (1.5.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using activesupport (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using builder (3.0.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using activemodel (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using erubis (2.7.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using journey (1.0.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rack (1.4.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rack-cache (1.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rack-test (0.6.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using hike (1.2.1) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using tilt (1.3.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using sprockets (2.2.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using actionpack (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using mime-types (1.19) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using polyglot (0.3.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using treetop (1.4.12) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using mail (2.4.4) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using actionmailer (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using arel (3.0.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using tzinfo (0.3.35) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using activerecord (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using activeresource (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using coffee-script-source (1.4.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using execjs (1.4.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using coffee-script (2.2.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rack-ssl (1.3.3) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using json (1.7.6) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rdoc (3.12) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using thor (0.17.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using railties (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using coffee-rails (3.2.2) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using jquery-rails (2.2.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using bundler (1.3.0.pre.5) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using rails (3.2.11) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using sass (3.2.5) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using sass-rails (3.2.6) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using sqlite3 (1.3.7) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using uglifier (1.3.0) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Your bundle is complete! It was installed into /Users/steve/tmp/vendor/bundle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;--path&lt;/code&gt; flag controls where the bundle is located. In this case, we store it one directory up. Now, when we copy new versions of the code over, it will use the bundle location that stays the same, and all is peachy keen.&lt;/p&gt;
&lt;p&gt;I am told by several people that this is what the Capistrano/bundler recipe does by default, so if you’re using that, you’re already doing this.&lt;/p&gt;
&lt;h2 id=&quot;one-tiny-weakness&quot;&gt;One Tiny Weakness&lt;/h2&gt;
&lt;p&gt;There is one small weakness of this approach compared to Vendor Everything: as an engineer, it’s your tradeoff to make.&lt;/p&gt;
&lt;p&gt;This way of using bundler &lt;em&gt;will&lt;/em&gt; hit the network &lt;em&gt;when you deploy for the first time after updating your bundle&lt;/em&gt;. The cache on the server has to update in this case, so it will go fetch the new gems. So here’s the scenario:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I update my bundle. It gets the new versions of the gems.&lt;/li&gt;
&lt;li&gt;Rubygems.org goes down.&lt;/li&gt;
&lt;li&gt;I need to deploy a branch that has the new versions in it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this case, if you had Vendored Everything, the hit to Rubygems.org would have happened during step 1, and so things would work. If you used this strategy, it would have hit locally, so you could have developed, but then when deploying, it’d hit again to update the bundle on the server, and so it wouldn’t.&lt;/p&gt;
&lt;p&gt;In these situations, you can temporarily switch to Vendor Everything, since you have the bundle installed locally: just copy your local gems over to &lt;code&gt;vendor/bundle&lt;/code&gt; and you’re done. This may or may not be too much of a hassle. When I examine the downtime of Rubygems.org, I think it’s worth it to not mess up my git repository with all that gem code. You might not. Do whatever you need to do, but now you know how to not rely on Rubygems.org for every deployment.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;an-addendum&quot;&gt;An addendum&lt;/h3&gt;
&lt;p&gt;I got an email mentioning one more issue with the ‘vendor everything’ strategy:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ ls vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/*.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/html_document.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/html_element_description.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/html_entity_lookup.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/html_sax_parser_context.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/html_sax_push_parser.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/nokogiri.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_attr.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_attribute_decl.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_cdata.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_comment.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_document.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_document_fragment.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_dtd.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_element_content.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_element_decl.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_encoding_handler.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_entity_decl.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_entity_reference.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_io.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_libxml2_hacks.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_namespace.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_node.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_node_set.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_processing_instruction.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_reader.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_relax_ng.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_sax_parser.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_sax_parser_context.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_sax_push_parser.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_schema.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_syntax_error.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_text.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xml_xpath_context.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor/bundle/ruby/1.9.1/gems/nokogiri-1.5.6/ext/nokogiri/xslt_stylesheet.o&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Basically, your compiled files get vendored, so if you’re, say, developing on Mac and deploying on Linux, you might end up with compiled native extensions for the totally wrong architecture.&lt;/p&gt;</content:encoded></item><item><title>Draper 1.0.0 released</title><link>https://steveklabnik.com/writing/draper-1-0-0-released/</link><guid isPermaLink="true">https://steveklabnik.com/writing/draper-1-0-0-released/</guid><description>Today, I released Draper 1.0.0! Draper is a gem that gives you decorators/view models for Rails. Rubygems: https://rubygems.org/gems/draper GitHub: https://github.com/drapergem/draper README: https://github.com/drapergem/draper/blob/master/README.md You can get it with Rubygems:…</description><pubDate>Mon, 14 Jan 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Today, I released Draper 1.0.0! Draper is a gem that gives you decorators/view models for Rails.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rubygems: &lt;a href=&quot;https://rubygems.org/gems/draper&quot;&gt;https://rubygems.org/gems/draper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href=&quot;https://github.com/drapergem/draper&quot;&gt;https://github.com/drapergem/draper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;README: &lt;a href=&quot;https://github.com/drapergem/draper/blob/master/README.md&quot;&gt;https://github.com/drapergem/draper/blob/master/README.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can get it with Rubygems:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ gem install draper&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or by adding this to your Gemfile:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;gem &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;draper&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;~&gt;1.0.0&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Draper supports all versions of Rails 3, and follows &lt;a href=&quot;http://semver.org/&quot;&gt;SemVer&lt;/a&gt;, so you can be confident that your application will work well with Draper in the future. Thank you to everyone who tried out our six (six!!!11) beta releases and gave us patches and feedback.&lt;/p&gt;</content:encoded></item><item><title>Rails has two default stacks</title><link>https://steveklabnik.com/writing/rails-has-two-default-stacks/</link><guid isPermaLink="true">https://steveklabnik.com/writing/rails-has-two-default-stacks/</guid><description>Rails’ greatest strength is “Convention over Configuration.” Basically, Rails makes a ton of default choices for you about how things should be named, where they should go, and other things. This is why working with Rails is so productive for an experienced developer: just follow…</description><pubDate>Mon, 14 Jan 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Rails’ greatest strength is “Convention over Configuration.” Basically, Rails makes a ton of default choices for you about how things should be named, where they should go, and other things. This is why working with Rails is so productive for an experienced developer: just follow the Golden Path and everything comes together quickly. It’s second greatest strength is its ‘full stack’ nature: Rails includes everything that you need to get going. It does not attempt to be ‘minimal’ in any way. Put these two things together, and a Rails app makes lots of assumptions about &lt;strong&gt;everything&lt;/strong&gt; in your app.&lt;/p&gt;
&lt;p&gt;But what happens when a significant number of people don’t use those defaults?&lt;/p&gt;
&lt;p&gt;First, let’s talk about the actual default stack. Since &lt;a href=&quot;http://david.heinemeierhansson.com/2012/rails-is-omakase.html&quot;&gt;Rails is omakase&lt;/a&gt;, I’m going to call this the ‘Omakase Stack.’ Roughly, this stack contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ERB for view templates&lt;/li&gt;
&lt;li&gt;MySQL for databases&lt;/li&gt;
&lt;li&gt;MiniTest for testing&lt;/li&gt;
&lt;li&gt;Fat Models, Skinny Controllers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There has been a ‘second default stack’ brewing for a while now. I’m going to call this the “&lt;a href=&quot;http://en.wikipedia.org/wiki/Prime_(symbol)%23Use_in_mathematics.2C_statistics.2C_and_science&quot;&gt;Prime&lt;/a&gt; stack”. This stack’s approximate choices are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Haml for view templates&lt;/li&gt;
&lt;li&gt;PostgreSQL for databases&lt;/li&gt;
&lt;li&gt;Rspec/Cucumber for testing&lt;/li&gt;
&lt;li&gt;Skinny models, controllers, and a service layer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is great! As David says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;That doesn’t mean patrons can’t express exceptions. Substitutions are allowed, within reason. So you don’t like test/unit? No problem, bring your own rspec. Don’t care for CoffeeScript as a dessert? Delete a single line from your Gemfile.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A considerable minority uses a stack like this. It’s important that the Prime Stack isn’t exact: you might not use Cucumber at all, for example, or maybe you don’t have a service layer. The important part, though, is that this is the new default you build preferences off of: a big group of people assumes that you don’t use MiniTest, you use Rspec, and the choice is Cukes or Capybara. This creates the ‘secondary default’ effect.&lt;/p&gt;
&lt;h2 id=&quot;dual-stack-ecology&quot;&gt;Dual Stack Ecology&lt;/h2&gt;
&lt;p&gt;So where’s the beef? Well, before I get into it, I want to make one thing explicit: I am &lt;em&gt;not&lt;/em&gt; taking a position on which stack, if any, is ‘better.’ I’m not interested, at least in this post, at placing them into any kind of order. That’s for another time. What I want to talk about here is about the effect that a second default stack has on the overall Rails ecosystem.&lt;/p&gt;
&lt;p&gt;Looking at history, the Prime Stack was born from the Omakase Stack. A certain group of people noticed that they were changing a significant amount of the stack most of the time, and so the Prime Stack came into existence. Since this is a historical progression, many blog posts got written describing the delta: take “&lt;a href=&quot;http://robots.thoughtbot.com/post/159807023/waiting-for-a-factory-girl&quot;&gt;Waiting for a Factory Girl&lt;/a&gt;”, for example.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here at thoughtbot, we’ve had it with fixtures.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But wait! Then, years later, you get a discussion on how factories are bad. My own “&lt;a href=&quot;/writing/why-i-don-t-like-factory_girl/&quot;&gt;Why I don’t like factory_girl&lt;/a&gt;” is an example:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;So that’s what it really boils down to: the convenience of factories has set Rails testing strategies and software design back two years.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Maybe a bit strongly worded. Anyway, the people who have created the Prime Stack also happen to be those who are vocal, blog a lot, and speak at a lot of conferences. Everybody loves a polemic. If I submitted a talk to RailsConf called “Why Fixtures are :metal:” this year, people would assume that I was being sarcastic. People always assume that things are slowly getting better: If the original advice was “use fixtures” and the new advice is “use Factories” and the &lt;em&gt;newest&lt;/em&gt; advice is “use neither”… there’s no way that the “right answer” is “use fixtures,” right? Isn’t that so 2007?&lt;/p&gt;
&lt;p&gt;For those of us who’ve been around Rails for a long time, this discussion is good, and interesting. I was able to search for that Factory Girl post by memory, because I remember reading it when it was posted. I’ve written tons of Rails apps in the past 6ish years, and formed my own opinions on what tools I want to use due to that experience.&lt;/p&gt;
&lt;p&gt;But what about someone starting Rails today?&lt;/p&gt;
&lt;h2 id=&quot;beginners-lose-out&quot;&gt;Beginners lose out&lt;/h2&gt;
&lt;p&gt;Someone told me earlier today that “Starting Rails today is like starting to watch a soap opera in the 7th season.” Like most witty statements, there’s both truth and falsehood here. But, as a newcomer, how do you pick between the Omakase Stack and the Prime Stack?&lt;/p&gt;
&lt;p&gt;This is the crux of the matter for me. If today, you tweeted that you were building a Rails app with fixtures, people would tell you to &lt;a href=&quot;http://www.youtube.com/watch?v=n-Tej0297wk&quot;&gt;Stop It&lt;/a&gt;. I saw it happen this morning. This is again, because a very vocal minority of Rails developers use the Prime Stack, and are really passionate about their choice over the Omakase Stack. That’s great.&lt;/p&gt;
&lt;p&gt;The problem is this: it puts a pretty heavy burden on a new developer: they have to learn the Omakase Stack &lt;strong&gt;and&lt;/strong&gt; the delta. At the moment when someone is new, and barely knows anything, we throw them into making &lt;em&gt;more&lt;/em&gt; choices. This is the moment when they’re least likely to be able to properly evaluate which option they need to choose. It’s not just “You’re new to Ruby, now learn Rails,” it’s now “You’re new to Ruby, now learn Rails, and RSpec, and Cucumber, and use this advanced modeling technique that we agree Rails discourages. Oh, and your only help is all these blog posts. Have fun!”&lt;/p&gt;
&lt;p&gt;As I said at the beginning of this post, Convention over Configuration is Rails’ greatest strength. So when a new person starts, the first thing we do is tell them to do a bunch of configuration. Any reasonable developer could easily ask “If these options really are so superior, why do I have to include them? And which do I choose? I’m drowning!”&lt;/p&gt;
&lt;h2 id=&quot;helping-people-build-better-apps&quot;&gt;Helping People Build Better Apps&lt;/h2&gt;
&lt;p&gt;We all want to write better, more maintainable apps. And many people (including me) are trying to push the state of the art forward in this regard. But we’re leaving the majority in the dust. Rather than trying to push the boundaries by choosing new techniques, maybe we should be helping people get better at existing ones, too. Because we need both approaches. There’s already so much to learn when building a Rails application, adding more gems and techniques to the pile just isn’t going to help.&lt;/p&gt;
&lt;p&gt;Once those beginners become intermediate, then they can figure out how new techniques solve the particular pains that they feel while going with the default flow. But skipping straight to the tool that solves my pain without feeling that pain the first place doesn’t help, it just confuses.&lt;/p&gt;
&lt;p&gt;Let’s keep pushing those boundaries, but let’s not &lt;em&gt;require&lt;/em&gt; someone to catch up on a few hundred episodes before they can understand what’s going on.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;If you read this post previously, the “Omakase Stack” was called the “37signals stack,” but David has pointed out &lt;a href=&quot;https://twitter.com/dhh/status/293108811219230720&quot;&gt;that even if he didn’t work with 37signals, he’d use this stack, so calling it that would be wrong&lt;/a&gt;. I’ve since changed the name.&lt;/p&gt;</content:encoded></item><item><title>Getting started with chruby</title><link>https://steveklabnik.com/writing/getting-started-with-chruby/</link><guid isPermaLink="true">https://steveklabnik.com/writing/getting-started-with-chruby/</guid><description>If you’re looking for crazy simplicity in your ‘switch between multiple Rubies’ life, you may want to check out chruby . Written by Postmodern, it’s basically the simplest possible thing that can work. As in, 76 lines of shell script . For that, you get: Features Updates $PATH .…</description><pubDate>Thu, 13 Dec 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you’re looking for crazy simplicity in your ‘switch between multiple Rubies’ life, you may want to check out &lt;a href=&quot;https://github.com/postmodern/chruby&quot;&gt;chruby&lt;/a&gt;. Written by Postmodern, it’s basically the simplest possible thing that can work. As in, &lt;a href=&quot;https://github.com/postmodern/chruby/blob/master/share/chruby/chruby.sh&quot;&gt;76 lines of shell script&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For that, you get:&lt;/p&gt;
&lt;h3 id=&quot;features&quot;&gt;Features&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Updates &lt;code&gt;$PATH&lt;/code&gt;.
&lt;ul&gt;
&lt;li&gt;Also adds RubyGems &lt;code&gt;bin/&lt;/code&gt; directories to &lt;code&gt;$PATH&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Correctly sets &lt;code&gt;$GEM_HOME&lt;/code&gt; and &lt;code&gt;$GEM_PATH&lt;/code&gt;.
&lt;ul&gt;
&lt;li&gt;Users: gems are installed into &lt;code&gt;~/.gem/$ruby/$version&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Root: gems are installed directly into &lt;code&gt;/path/to/$ruby/$gemdir&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Additionally sets &lt;code&gt;$RUBY&lt;/code&gt;, &lt;code&gt;$RUBY_ENGINE&lt;/code&gt;, &lt;code&gt;$RUBY_VERSION&lt;/code&gt; and &lt;code&gt;$GEM_ROOT&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Optionally sets &lt;code&gt;$RUBYOPT&lt;/code&gt; if second argument is given.&lt;/li&gt;
&lt;li&gt;Calls &lt;code&gt;hash -r&lt;/code&gt; to clear the command-lookup hash-table.&lt;/li&gt;
&lt;li&gt;Fuzzy matching of Rubies by name.&lt;/li&gt;
&lt;li&gt;Defaults to the system Ruby.&lt;/li&gt;
&lt;li&gt;Supports [bash] and [zsh].&lt;/li&gt;
&lt;li&gt;Small (~80 LOC).&lt;/li&gt;
&lt;li&gt;Has tests.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;anti-features&quot;&gt;Anti-Features&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Does not hook &lt;code&gt;cd&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Does not install executable shims.&lt;/li&gt;
&lt;li&gt;Does not require Rubies be installed into your home directory.&lt;/li&gt;
&lt;li&gt;Does not automatically switch Rubies upon login or when changing directories.&lt;/li&gt;
&lt;li&gt;Does not require write-access to the Ruby directory in order to install gems.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Kinda crazy, eh?&lt;/p&gt;
&lt;h2 id=&quot;installing&quot;&gt;Installing&lt;/h2&gt;
&lt;p&gt;Most of the time, I install things from &lt;code&gt;homebrew&lt;/code&gt;, but I actually prefered to run the &lt;code&gt;setup.sh&lt;/code&gt; script:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;wget https://github.com/downloads/postmodern/chruby/chruby-0.2.3.tar.gz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;tar -xzvf chruby-0.2.3.tar.gz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;cd chruby-0.2.3/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;./scripts/setup.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can see the source for that script &lt;a href=&quot;https://github.com/postmodern/chruby/blob/master/scripts/setup.sh&quot;&gt;here&lt;/a&gt;. You’ll end up with an MRI, JRuby, and Rubinius all installed in &lt;code&gt;/opt/rubies&lt;/code&gt;, and after restarting your shell, you should be good to go!&lt;/p&gt;
&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;/h2&gt;
&lt;p&gt;To see what Rubies you’ve got, just &lt;code&gt;chruby&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ chruby&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   ruby-1.9.3-p327&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   jruby-1.7.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   rubinius-2.0.0-rc1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to pick one:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ chruby 1.9.3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pretty damn simple.&lt;/p&gt;
&lt;h2 id=&quot;getting-more-rubies&quot;&gt;Getting more Rubies?&lt;/h2&gt;
&lt;p&gt;The setup script will install &lt;a href=&quot;https://github.com/sstephenson/ruby-build#readme&quot;&gt;ruby-build&lt;/a&gt;, so just use that to get more rubies:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ruby-build 1.9.3-p327 /opt/rubies/ruby-1.9.3-p327&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You’ll then need to update your list of Rubies in your &lt;code&gt;.bashrc&lt;/code&gt; or &lt;code&gt;.zshrc&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;RUBIES=(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  # other rubies here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  /opt/rubies/ruby-1.9.3-p327&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you find this tedius, you can just glob them:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;RUBIES=(/opt/rubies/*)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;automatic-switching&quot;&gt;Automatic switching?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/postmodern/chruby/issues/40&quot;&gt;Not yet&lt;/a&gt;. This is pretty much the only thing keeping me from saying ‘zomg use this for sure now.’&lt;/p&gt;
&lt;h2 id=&quot;how-good-is-it&quot;&gt;How good is it?&lt;/h2&gt;
&lt;p&gt;I don’t know, I’ve been using it for less than 24 hours. Seems good.&lt;/p&gt;</content:encoded></item><item><title>Draper 1.0.0.beta2 release</title><link>https://steveklabnik.com/writing/draper-1-0-0-beta2-release/</link><guid isPermaLink="true">https://steveklabnik.com/writing/draper-1-0-0-beta2-release/</guid><description>I’ve relased the second beta for Draper 1.0.0! Many thanks to all of you who gave the first beta a shot. We’ve fixed some issues, and I’d apprecaite you giving this one a try. This solves all known issues with Draper, including every one we’ve found in 1.0.0.beta1. You can get it…</description><pubDate>Mon, 03 Dec 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’ve relased the second beta for Draper 1.0.0! Many thanks to all of you who gave the first beta a shot. We’ve fixed some issues, and I’d apprecaite you giving this one a try. This solves all known issues with Draper, including every one we’ve found in 1.0.0.beta1.&lt;/p&gt;
&lt;p&gt;You can get it by installing it from Rubygems:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ gem install draper --pre&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or by putting it in your Gemfile:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;gem &quot;draper&quot;, &quot;1.0.0.beta2&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;changelog&quot;&gt;CHANGELOG&lt;/h2&gt;
&lt;p&gt;These are the changes since beta1. To find out what’s new in beta1, please &lt;a href=&quot;/posts/2012-11-30-draper-1-0-0-beta1-release&quot;&gt;see my previous post&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;has_finders&lt;/code&gt; is now &lt;code&gt;decorates_finders&lt;/code&gt;. &lt;a href=&quot;https://github.com/haines/draper/commit/33f18aa062e0d3848443dbd81047f20d5665579f&quot;&gt;https://github.com/haines/draper/commit/33f18aa062e0d3848443dbd81047f20d5665579f&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;If a finder method is used, and the source class is not set and cannot be inferred, an &lt;code&gt;UninferrableSourceError&lt;/code&gt; is raised. &lt;a href=&quot;https://github.com/haines/draper/commit/8ef5bf2f02f7033e3cd4f1f5de7397b02c984fe3&quot;&gt;https://github.com/haines/draper/commit/8ef5bf2f02f7033e3cd4f1f5de7397b02c984fe3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Class methods are now properly delegated again. &lt;a href=&quot;https://github.com/haines/draper/commit/731995a5feac4cd06cf9328d2892c0eca9992db6&quot;&gt;https://github.com/haines/draper/commit/731995a5feac4cd06cf9328d2892c0eca9992db6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;We no longer &lt;code&gt;respond_to?&lt;/code&gt; private methods on the source. &lt;a href=&quot;https://github.com/haines/draper/commit/18ebac81533a6413aa20a3c26f23e91d0b12b031&quot;&gt;https://github.com/haines/draper/commit/18ebac81533a6413aa20a3c26f23e91d0b12b031&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Rails versioning relaxed to support Rails 4 &lt;a href=&quot;https://github.com/drapergem/draper/commit/8bfd393b5baa7aa1488076a5e2cb88648efaa815&quot;&gt;https://github.com/drapergem/draper/commit/8bfd393b5baa7aa1488076a5e2cb88648efaa815&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Draper 1.0.0.beta1 release</title><link>https://steveklabnik.com/writing/draper-1-0-0-beta1-release/</link><guid isPermaLink="true">https://steveklabnik.com/writing/draper-1-0-0-beta1-release/</guid><description>I’m happy to announce the release of Draper 1.0.0.beta1 today. If you use Draper, I’d appreciate you checking out the beta release in your app, kicking the tires, and letting me know what’s up. You can get it by installing it from Rubygems: $ gem install draper --pre or by…</description><pubDate>Fri, 30 Nov 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’m happy to announce the release of Draper 1.0.0.beta1 today. If you use Draper, I’d appreciate you checking out the beta release in your app, kicking the tires, and letting me know what’s up.&lt;/p&gt;
&lt;p&gt;You can get it by installing it from Rubygems:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ gem install draper --pre&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or by putting it in your Gemfile:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;gem &quot;draper&quot;, &quot;1.0.0.beta1&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notable changes include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Renaming &lt;code&gt;Draper::Base&lt;/code&gt; to &lt;code&gt;Draper::Decorator&lt;/code&gt;. This is the most significant change you’ll need to upgrade your application. &lt;a href=&quot;https://github.com/drapergem/draper/commit/025742cb3b295d259cf0ecf3669c24817d6f2df1&quot;&gt;https://github.com/drapergem/draper/commit/025742cb3b295d259cf0ecf3669c24817d6f2df1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Added an internal Rails application for integration tests. This won’t affect your application, but we’re now running a set of Cucumber tests inside of a Rails app in both development and production mode to help ensure that we don’t make changes that break Draper. &lt;a href=&quot;https://github.com/drapergem/draper/commit/90a4859085cab158658d23d77cd3108b6037e36f&quot;&gt;https://github.com/drapergem/draper/commit/90a4859085cab158658d23d77cd3108b6037e36f&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;#decorated?&lt;/code&gt; method. This gives us a free RSpec matcher, &lt;code&gt;is_decorated?&lt;/code&gt;. &lt;a href=&quot;https://github.com/drapergem/draper/commit/834a6fd1f24b5646c333a04a99fe9846a58965d6&quot;&gt;https://github.com/drapergem/draper/commit/834a6fd1f24b5646c333a04a99fe9846a58965d6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#decorates&lt;/code&gt; is no longer needed inside your models, and should be removed. Decorators automatically infer the class they decorate. &lt;a href=&quot;https://github.com/drapergem/draper/commit/e1214d97b62f2cab45227cc650029734160dcdfe&quot;&gt;https://github.com/drapergem/draper/commit/e1214d97b62f2cab45227cc650029734160dcdfe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Decorators do not automatically come with ‘finders’ by default. If you’d like to use &lt;code&gt;SomeDecorator.find(1)&lt;/code&gt;, for example, simply add &lt;code&gt;#has_finders&lt;/code&gt; to the decorator to include them. &lt;a href=&quot;https://github.com/drapergem/draper/commit/42b6f78fda4f51845dab4d35da68880f1989d178&quot;&gt;https://github.com/drapergem/draper/commit/42b6f78fda4f51845dab4d35da68880f1989d178&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;To refer to the object being decorated, &lt;code&gt;#source&lt;/code&gt; is now the preferred method. &lt;a href=&quot;https://github.com/drapergem/draper/commit/1e84fcb4a0eab0d12f5feda6886ce1caa239cb16&quot;&gt;https://github.com/drapergem/draper/commit/1e84fcb4a0eab0d12f5feda6886ce1caa239cb16&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ActiveModel::Serialization&lt;/code&gt; is included in Decorators if you’ve requred &lt;code&gt;ActiveModel::Serializers&lt;/code&gt;, so that decorators can be serialized. &lt;a href=&quot;https://github.com/drapergem/draper/commit/c4b352799067506849abcbf14963ea36abda301c&quot;&gt;https://github.com/drapergem/draper/commit/c4b352799067506849abcbf14963ea36abda301c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Properly support Test::Unit &lt;a href=&quot;https://github.com/drapergem/draper/commit/087e134ed0885ec11325ffabe8ab2bebef77a33a&quot;&gt;https://github.com/drapergem/draper/commit/087e134ed0885ec11325ffabe8ab2bebef77a33a&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And many small bug fixes and refactorings.&lt;/p&gt;
&lt;p&gt;Before the actual release of 1.0.0, I want to improve documentation and handle a few other things, but we currently have no confirmed and one possible bug in Draper as it stands, so your feedback as I clean up these last few things would be excellent. Please file issues on the tracker if you find anything.&lt;/p&gt;
&lt;p&gt;Thank you! &amp;#x3C;3 &amp;#x3C;3 &amp;#x3C;3&lt;/p&gt;</content:encoded></item><item><title>Introducing the rails-api project</title><link>https://steveklabnik.com/writing/introducing-the-rails-api-project/</link><guid isPermaLink="true">https://steveklabnik.com/writing/introducing-the-rails-api-project/</guid><description>Ruby on Rails is a great tool to build websites incredibly quickly and easily. But what about applications that aren’t websites? Rails is still a first-class choice for this use-case, but why settle for good when you could be the best? That’s why I’m happy to introduce Rails API:…</description><pubDate>Thu, 22 Nov 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Ruby on Rails is a great tool to build websites incredibly quickly and easily. But what about applications that aren’t websites? Rails is still a first-class choice for this use-case, but why settle for good when you could be the best?&lt;/p&gt;
&lt;p&gt;That’s why I’m happy to introduce Rails API: a set of tools to build excellent APIs for both heavy Javascript applications as well as non-Web API clients.&lt;/p&gt;
&lt;h2 id=&quot;what&quot;&gt;What&lt;/h2&gt;
&lt;p&gt;Rails’ greatest feature is making trivial choices for you. By following conventions, you’re able to avoid bikeshedding and only focus on the actual decisions that matter for your application, while automatically building in best-practices. Rails API will do this for the API use-case.&lt;/p&gt;
&lt;p&gt;Here are some initial thoughts on what Rails API will do for you:&lt;/p&gt;
&lt;h3 id=&quot;a-simpler-stack&quot;&gt;A simpler stack&lt;/h3&gt;
&lt;p&gt;First, we can remove many parts of Rails that aren’t important in an API context: many middleware don’t make sense, and all of ActionView can go away.&lt;/p&gt;
&lt;p&gt;To check out exactly what we mean, look at &lt;a href=&quot;https://github.com/rails-api/rails-api#choosing-middlewares&quot;&gt;this part&lt;/a&gt; of the README, which explains which middlewares we include. The default stack has 22, we have 14.&lt;/p&gt;
&lt;p&gt;Similarly, the structure of ActionController::Base is interesting: it includes a ton of modules that implement various features. This means that we can build an alternate ‘controller stack’ that doesn’t include all of the ones that are in Base. Check out &lt;a href=&quot;https://github.com/rails-api/rails-api#choosing-controller-modules&quot;&gt;this portion&lt;/a&gt; of the README for a demonstration of the modules we do include. Base includes 29 modules, we include 11.&lt;/p&gt;
&lt;h3 id=&quot;consistent-javascript-output&quot;&gt;Consistent Javascript output&lt;/h3&gt;
&lt;p&gt;One of the biggest issues when building a distributed system is messages that are sent between components. In most Rails-based APIs, this means the JSON that your server side emits, and the JSON that your client consumes. By forming best practices around what JSON is sent around, we can simplify things for server-side and client-side developers.&lt;/p&gt;
&lt;p&gt;The generation of this JSON should be as transparent and simple as possible on both sides. &lt;a href=&quot;https://github.com/rails-api/active_model_serializers&quot;&gt;ActiveModel::Serializers&lt;/a&gt; is key here. Many new APIs are settling on HAL as a JSON variant that is important to them, and so we’ll be considering it heavily.&lt;/p&gt;
&lt;h3 id=&quot;authentication&quot;&gt;Authentication&lt;/h3&gt;
&lt;p&gt;APIs don’t need to handle cookie-based auth, and so a lot of that infrastructure isn’t important. Handling other kinds of auth in a simple way is incredibly important.&lt;/p&gt;
&lt;h3 id=&quot;javascript-as-a-first-class-citizen&quot;&gt;JavaScript as a first-class citizen&lt;/h3&gt;
&lt;p&gt;JavaScript is just as important as Ruby for these kinds of applications, and should be equally as important with respect to tooling, directory layout, and documentation.&lt;/p&gt;
&lt;p&gt;This also means that it should be easy to use the various Javascript frameworks and testing tools. We have representatives from the Ember team on-board, but using other frameworks should be equally fantastic.&lt;/p&gt;
&lt;h3 id=&quot;hypermedia&quot;&gt;Hypermedia&lt;/h3&gt;
&lt;p&gt;Many people are interested in building Hypermedia APIs on top of Rails, and so building best-practices around this style should be taken care of, and building them should be easy.&lt;/p&gt;
&lt;h2 id=&quot;where&quot;&gt;Where&lt;/h2&gt;
&lt;p&gt;You can find the organization on GitHub at &lt;a href=&quot;https://github.com/rails-api&quot;&gt;https://github.com/rails-api&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Originally, these two repositories were located at &lt;a href=&quot;https://github.com/spastorino/rails-api&quot;&gt;https://github.com/spastorino/rails-api&lt;/a&gt; and &lt;a href=&quot;https://github.com/josevalim/active_model_serializers&quot;&gt;https://github.com/josevalim/active_model_serializers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We have a Google Group for discussion here: &lt;a href=&quot;https://groups.google.com/forum/?fromgroups#!forum/rails-api-core&quot;&gt;https://groups.google.com/forum/?fromgroups#!forum/rails-api-core&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;To get started, check out the README here: &lt;a href=&quot;https://github.com/rails-api/rails-api#railsapi&quot;&gt;https://github.com/rails-api/rails-api#railsapi&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;who&quot;&gt;Who&lt;/h2&gt;
&lt;p&gt;Currently,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Carlos Antonio&lt;/li&gt;
&lt;li&gt;Rafael França&lt;/li&gt;
&lt;li&gt;Santiago Pastorino&lt;/li&gt;
&lt;li&gt;Steve Klabnik&lt;/li&gt;
&lt;li&gt;Yehuda Katz&lt;/li&gt;
&lt;li&gt;Tom Dale&lt;/li&gt;
&lt;li&gt;José Valim&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Run Rails with custom patches</title><link>https://steveklabnik.com/writing/run-rails-with-custom-patches/</link><guid isPermaLink="true">https://steveklabnik.com/writing/run-rails-with-custom-patches/</guid><description>I often see comments like this in the Rails bugtracker. Generally, someone is running an older version of Rails, and some bug they face has been fixed on edge. But they may be running a version that’s too old to receive fixes, or need a fix that has yet to be included in an…</description><pubDate>Thu, 04 Oct 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I often see comments &lt;a href=&quot;https://github.com/rails/rails/pull/7397#issuecomment-9132009&quot;&gt;like this&lt;/a&gt; in the Rails bugtracker. Generally, someone is running an older version of Rails, and some bug they face has been fixed on edge. But they may be running a version that’s too old to receive fixes, or need a fix that has yet to be included in an actual release. What to do?&lt;/p&gt;
&lt;p&gt;Luckily, &lt;a href=&quot;http://gembundler.com/&quot;&gt;Bundler&lt;/a&gt; exists. It makes it super easy to run your own Rails. Check it out:&lt;/p&gt;
&lt;h2 id=&quot;step-1-fork-you&quot;&gt;Step 1: Fork you!&lt;/h2&gt;
&lt;p&gt;Go to GitHub, hit up &lt;a href=&quot;http://github.com/rails/rails&quot;&gt;rails/rails&lt;/a&gt;, and click that fork button. My own personal fork of Rails is &lt;a href=&quot;https://github.com/steveklabnik/rails&quot;&gt;here&lt;/a&gt;, for example, so in the rest of these examples, I’ll be using my own username. If you’re me, you can use it too, but seriously, stop being me. If you’re not me, substitute your own username.&lt;/p&gt;
&lt;h2 id=&quot;step-2-apply-patch&quot;&gt;Step 2: apply patch&lt;/h2&gt;
&lt;p&gt;Let’s get our copy going locally:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ git clone git@github.com:steveklabnik/rails.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ cd rails&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We’ll apply the patch from the example comment above. In this case, the person wants to have this patch work on Rails 3.1.&lt;/p&gt;
&lt;p&gt;You have two options here: Rails keeps a branch open for every minor version, and also tags every release. You can pick between the stable branch and a particular release. The stable branch should work just fine, but maybe you’re on a specific Rails release for a reason. For example, the latest version of Rails 3.1 is 3.1.8, but this person says they’re on 3.1.1. If they use the 3-1-stable branch, they’ll also get all the changes from 3.1.1-3.1.8, as well as unreleased changes that may exist on that branch. That’s possibly too much for you, so we’ll just work off of 3.1.1. This is probably a bad idea, since &lt;a href=&quot;http://weblog.rubyonrails.org/2012/6/12/ann-rails-3-1-6-has-been-released/&quot;&gt;3.1.6 included several security fixes&lt;/a&gt;, but you’re an adult, do dumb things if you want to.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ git checkout v3.1.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You’ll see a big message about a detached HEAD. Don’t worry about it.&lt;/p&gt;
&lt;p&gt;If you want the stable branch for extra fixes,&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ git checkout 3-1-stable&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, it’s a good idea to make our own branches, so that we don’t get confused with upstream. So let’s make a new branch:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ git checkout -b my_patched_rails&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Awesome. Now, we can grab the commit we wanted. We can do this with &lt;code&gt;cherry-pick&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ git cherry-pick 8fc8763fde2cc685ed63fcf640cfae556252809b&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I found this SHA1 by checking out &lt;a href=&quot;https://github.com/rails/rails/pull/7397/commits&quot;&gt;this page&lt;/a&gt;, which is linked at the top of the pull request.&lt;/p&gt;
&lt;p&gt;If there are multiple commits you need, you can do one of two things: either &lt;code&gt;cherry-pick&lt;/code&gt; the merge commit, in which case you’ll probably need to pass the &lt;code&gt;-m1&lt;/code&gt; option, or simply &lt;code&gt;cherry-pick&lt;/code&gt; them all in order.&lt;/p&gt;
&lt;p&gt;You may get conflicts. Yay backporting! If &lt;code&gt;git&lt;/code&gt; whines at you, do what you normally do. Resolve the merge, then &lt;code&gt;git commit&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Finally, push it back up to your GitHub:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ git push origin my_patched_rails&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Congrats! You’ve got your own custom Rails. Now it’s time to use it.&lt;/p&gt;
&lt;h2 id=&quot;step-3-update-gemfile&quot;&gt;Step 3: update Gemfile&lt;/h2&gt;
&lt;p&gt;Go to your Rails app, and edit this line in your Gemfile:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;gem &apos;rails&apos;, &quot;3.1.1&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;change it to this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;gem &apos;rails&apos;, :git =&gt; &quot;https://github.com/steveklabnik/rails&quot;, :branch =&gt; &quot;my_patched_rails&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’s that easy! Now bundle:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ bundle update&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You should see it mention something about checking out a certain copy of Rails.&lt;/p&gt;
&lt;h2 id=&quot;step-4-profit&quot;&gt;Step 4: Profit!&lt;/h2&gt;
&lt;p&gt;That’s it! Congrats, you’re using Rails with your patch.&lt;/p&gt;
&lt;h2 id=&quot;but-im-on-23-im-not-running-bundler&quot;&gt;But I’m on 2.3, I’m not running Bundler!&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://gembundler.com/v0.9/rails23.html&quot;&gt;Do this&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Resque: let&apos;s do this</title><link>https://steveklabnik.com/writing/resque--let-s-do-this/</link><guid isPermaLink="true">https://steveklabnik.com/writing/resque--let-s-do-this/</guid><description>If you’ve ever done background job stuff with Rails, you’ve probably used Resque . Resque is “Yet Another GitHub Project They’ve Open Sourced and Then Abandoned.” But Resque is super awesome: it builds a job queue on top of Redis, which is a totally awesome piece of software.…</description><pubDate>Sat, 22 Sep 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you’ve ever done background job stuff with Rails, you’ve probably used &lt;a href=&quot;https://github.com/defunkt/resque&quot;&gt;Resque&lt;/a&gt;. Resque is “Yet Another GitHub Project They’ve Open Sourced and Then Abandoned.” But Resque is super awesome: it builds a job queue on top of Redis, which is a totally awesome piece of software.&lt;/p&gt;
&lt;p&gt;Anyway, Resque has been psuedo-abandonware for a while now. In January, &lt;a href=&quot;http://hone.heroku.com/&quot;&gt;Terence Lee&lt;/a&gt; from Heroku got in charge of the project, but it’s a big job. Too big of a job to properly manage alone. It’s hard to sift through &lt;a href=&quot;https://github.com/defunkt/resque/issues?state=open&quot;&gt;60 pulls and 120 open issues&lt;/a&gt;, some of which have been open for a few &lt;em&gt;years&lt;/em&gt;. And manage the 1.x line while working on new stuff for 2.0. And debug issues that basically boil down to “When I upgrade Resque and this random gem, everything breaks, but when I downgrade that other gem, it works again. But Resque throws the error.”&lt;/p&gt;
&lt;p&gt;Even outside of heroics, the bus factor on a project that’s as important as Resque should be higher than one.&lt;/p&gt;
&lt;p&gt;So Terrence gave a presentation at Frozen Rails, and in it, he outlined what needs to be done for Resque 2.0, and asked for some help getting it out the door. So myself and a few other people are gonna pitch in and help out, and we’d love to have you.&lt;/p&gt;
&lt;p&gt;Here’s the deal: I will personally be looking at (and already have read) every single open issue on GitHub. Feel ignored about something involving Resque? You can come to me. I can’t guarantee that I can get it fixed, but at least I’ll help you figure out wtf is going on, and get us a bug report that we can use to build a fix.&lt;/p&gt;
&lt;p&gt;Think of it as decoupling the front end from the back end: Terrence can focus on writing new code, and I can focus on paying attention to your problems, helping you solve them, and getting fixes applied to the 1.x branch.&lt;/p&gt;
&lt;p&gt;If you’re interested in helping out, we’d love to have you. Helping triage issues would be awesome, fixing bugs would be awesome, writing code would be awesome, updating docs would be awesome.&lt;/p&gt;
&lt;p&gt;Let’s do this.&lt;/p&gt;</content:encoded></item><item><title>Random Ruby Tricks: Class.new</title><link>https://steveklabnik.com/writing/random-ruby-tricks--class-new/</link><guid isPermaLink="true">https://steveklabnik.com/writing/random-ruby-tricks--class-new/</guid><description>If you didn’t know, classes are first-class objects in Ruby: 1.9.3p194 :001 &gt; String.class =&gt; Class 1.9.3p194 :002 &gt; Class.class =&gt; Class How is this useful, though? Inheritance You may create very simple classes at times. This often happens when subclassing an error of some…</description><pubDate>Sun, 09 Sep 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you didn’t know, classes are first-class objects in Ruby:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1.9.3p194 :001 &gt; String.class&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; =&gt; Class &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1.9.3p194 :002 &gt; Class.class&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; =&gt; Class&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How is this useful, though?&lt;/p&gt;
&lt;h2 id=&quot;inheritance&quot;&gt;Inheritance&lt;/h2&gt;
&lt;p&gt;You may create very simple classes at times. This often happens when subclassing an error of some sort:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; MyException&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;StandardError&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;raise&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; MyException&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That whole thing is awkward to me, though. Why bother with the end if you don’t need it? Turns out, it’s easy to make your own &lt;code&gt;Class&lt;/code&gt; object: just use &lt;code&gt;Class.new&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1.9.3p194 :001 &gt; Class.new&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; =&gt; #&amp;#x3C;Class:0x007fee209f42f8&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But that doesn’t help us a ton. Turns out &lt;code&gt;Class.new&lt;/code&gt; takes an argument: the class this new class inherits from:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1.9.3p194 :002 &gt; Class.new(StandardError)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; =&gt; #&amp;#x3C;Class:0x007fee209ee2e0&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can then save this in our own constant:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1.9.3p194 :003 &gt; MyException = Class.new(StandardError)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; =&gt; MyException &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1.9.3p194 :004 &gt; MyException.new&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; =&gt; #&amp;#x3C;MyException: MyException&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1.9.3p194 :005 &gt; MyException.ancestors&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; =&gt; [MyException, StandardError, Exception, Object, Kernel, BasicObject]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I think I like this notation a bit better than &lt;code&gt;class...end&lt;/code&gt;. But many people may not be familiar with it.&lt;/p&gt;
&lt;h2 id=&quot;passing-a-block&quot;&gt;Passing a block&lt;/h2&gt;
&lt;p&gt;Of course, you can pass a block to &lt;code&gt;Class.new&lt;/code&gt; and it’ll work like you’d expect:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1.9.3p194 :001 &gt; Foo = Class.new do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1.9.3p194 :002 &gt;     def bar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1.9.3p194 :003?&gt;     puts &quot;bar&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1.9.3p194 :004?&gt;     end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1.9.3p194 :005?&gt;   end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; =&gt; Foo &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1.9.3p194 :006 &gt; Foo.new.bar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;bar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; =&gt; nil&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The block gets &lt;code&gt;class_eval&lt;/code&gt;’d. I haven’t found a good use for this one, exactly, but it’s good to know about!&lt;/p&gt;
&lt;p&gt;EDIT: &lt;a href=&quot;https://twitter.com/pete_higgins/status/244903490588119040&quot;&gt;@pete_higgins has chimed in on Twitter.&lt;/a&gt; I knew I’d done this before!&lt;/p&gt;
&lt;h2 id=&quot;new-vs-initialize&quot;&gt;&lt;code&gt;new&lt;/code&gt; vs &lt;code&gt;initialize&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Ever wonder why you call &lt;code&gt;Foo.new&lt;/code&gt; but define &lt;code&gt;Foo.initialize&lt;/code&gt;? It’s pretty simple. Here:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;VALUE &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;rb_class_new_instance&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; argc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, VALUE &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;argv&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, VALUE &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;klass&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    VALUE obj;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    obj &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; rb_obj_alloc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(klass);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    rb_obj_call_init&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(obj, argc, argv);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; obj;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Obviously! This is the source for &lt;code&gt;Foo.new&lt;/code&gt;. You might not read C, but it’s pretty simple: it first allocates the space for the object using &lt;code&gt;rb_obj_alloc&lt;/code&gt;, and then calls &lt;code&gt;initialize&lt;/code&gt; using &lt;code&gt;rb_obj_call_init&lt;/code&gt;.&lt;/p&gt;</content:encoded></item><item><title>Random Ruby Tricks: Struct.new</title><link>https://steveklabnik.com/writing/random-ruby-tricks--struct-new/</link><guid isPermaLink="true">https://steveklabnik.com/writing/random-ruby-tricks--struct-new/</guid><description>One of my favorite classes in Ruby is Struct , but I feel like many Rubyists don’t know when to take advantage of it. The standard library has a lot of junk in it, but Struct and OStruct are super awesome. Struct If you haven’t used Struct before, here’s the documentation of…</description><pubDate>Sat, 01 Sep 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;One of my favorite classes in Ruby is &lt;code&gt;Struct&lt;/code&gt;, but I feel like many Rubyists don’t know when to take advantage of it. The standard library has a lot of junk in it, but &lt;code&gt;Struct&lt;/code&gt; and &lt;code&gt;OStruct&lt;/code&gt; are super awesome.&lt;/p&gt;
&lt;h2 id=&quot;struct&quot;&gt;Struct&lt;/h2&gt;
&lt;p&gt;If you haven’t used &lt;code&gt;Struct&lt;/code&gt; before, here’s &lt;a href=&quot;http://www.ruby-doc.org/core-1.9.3/Struct.html&quot;&gt;the documentation of Struct from the Ruby standard library&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Structs are used to create super simple classes with some instance variables and a simple constructor. Check it:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Point&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:x&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:y&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#=&gt; Struct::Point&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;origin&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Point&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#=&gt; #&amp;#x3C;struct Struct::Point x=0, y=0&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nobody uses it this way, though. Here’s the way I first saw it used:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Point&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:x&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:y&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;origin&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Point&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wait, what? Inherit…from an instance of something? Yep!&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1.9.3p194 :001 &gt; Struct.new(:x,:y)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; =&gt; #&amp;#x3C;Class:0x007f8fc38da2e8&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Struct.new&lt;/code&gt; gives us a &lt;code&gt;Class&lt;/code&gt;. We can inherit from this just like any other &lt;code&gt;Class&lt;/code&gt;. Neat!&lt;/p&gt;
&lt;p&gt;However, if you’re gonna make an empty class like this, I prefer this way:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Point&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:x&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:y&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;origin&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Point&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yep. Classes are just constants, so we assign a constant to that particular &lt;code&gt;Class&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;ostruct&quot;&gt;OStruct&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://ruby-doc.org/stdlib-1.9.3/libdoc/ostruct/rdoc/OpenStruct.html&quot;&gt;OStruct&lt;/a&gt;s are like &lt;code&gt;Struct&lt;/code&gt; on steroids. Check it:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;ostruct&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;origin&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; OpenStruct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;origin.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;origin.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;y&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;origin&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; OpenStruct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:x&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:y&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;OStruct&lt;/code&gt;s are particularly good for configuration objects. Since any method works to set data in an &lt;code&gt;OStruct&lt;/code&gt;, you don’t have to worry about enumerating every single option that you need:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;ostruct&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; set_options&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  opts&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; OpenStruct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  yield&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; opts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  opts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;options&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; set_options &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; |o|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  o.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;set_foo&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  o.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;load_path&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;whatever:something&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;options &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#=&gt; #&amp;#x3C;OpenStruct set_foo=true, load_path=&quot;whatever:something&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Neat, eh?&lt;/p&gt;
&lt;h2 id=&quot;structs-for-domain-concepts&quot;&gt;Structs for domain concepts&lt;/h2&gt;
&lt;p&gt;You can use &lt;code&gt;Struct&lt;/code&gt;s to help reify domain concepts into simple little classes. For example, say we have this code, which uses a date:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Person&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  attr_accessor&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; :name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:day&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:month&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:year&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(opts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @name &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; opts[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @day &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; opts[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:day&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @month &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; opts[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:month&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @year &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; opts[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:year&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; birthday&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;#@day&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;#@month&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;#@year&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we have this spec&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$:.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;unshift&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;lib&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;person&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;describe &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Person&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  it &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;compares birthdays&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    joe&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Person&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Joe&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:day&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:month&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:year&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1986&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    jon&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Person&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Jon&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:day&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:month&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:year&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1986&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    joe.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;birthday&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;should&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jon.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;birthday&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It fails, of course. Like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ rspec&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;F&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Failures:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  1) Person compares birthdays&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     Failure/Error: joe.birthday.should == jon.birthday&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       expected: &quot;7/6/1986&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            got: &quot;5/6/1986&quot; (using ==)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     # ./spec/person_spec.rb:9:in `block (2 levels) in &amp;#x3C;top (required)&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Finished in 0.00053 seconds&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1 example, 1 failure&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Failed examples:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;rspec ./spec/person_spec.rb:5 # Person compares birthdays&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now. We have these two birthdays. In this case, we know about why the test was failing, but imagine this failure in a real codebase. Are these month/day/year or day/month/year? You can’t tell, it could be either. If we switched our code to this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Person&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  attr_accessor&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; :name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:birthday&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  Birthday&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:day&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:month&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:year&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(opts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @name &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; opts[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @birthday &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Birthday&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(opts[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:day&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], opts[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:month&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], opts[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:year&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We get this failure instead:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ rspec&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;F&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Failures:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  1) Person compares birthdays&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     Failure/Error: joe.birthday.should == jon.birthday&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       expected: #&amp;#x3C;struct Person::Birthday day=7, month=6, year=1986&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            got: #&amp;#x3C;struct Person::Birthday day=5, month=6, year=1986&gt; (using ==)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       Diff:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       @@ -1,2 +1,2 @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       -#&amp;#x3C;struct Person::Birthday day=7, month=6, year=1986&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       +#&amp;#x3C;struct Person::Birthday day=5, month=6, year=1986&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     # ./spec/person_spec.rb:9:in `block (2 levels) in &amp;#x3C;top (required)&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Finished in 0.00092 seconds&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1 example, 1 failure&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Failed examples:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;rspec ./spec/person_spec.rb:5 # Person compares birthdays&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We have a way, way more clear failure. We can clearly see that its our days that are off.&lt;/p&gt;
&lt;p&gt;Of course, there are other good reasons to package related instance variables into &lt;code&gt;Struct&lt;/code&gt;s, too: it makes more conceptual sense. This code represents our intent better: a Person has a Birthday, they don’t have three unrelated numbers stored inside them somehow. If we need to add something to our concept of birthdays, we now have a place to put it.&lt;/p&gt;</content:encoded></item><item><title>Why I don&apos;t like factory_girl</title><link>https://steveklabnik.com/writing/why-i-don-t-like-factory_girl/</link><guid isPermaLink="true">https://steveklabnik.com/writing/why-i-don-t-like-factory_girl/</guid><description>Once upon a time, I was building my First Serious Rails App. I was drawn to Rails in the first place because of automated testing and ActiveRecord; I felt the pain of not using an ORM and spending about a week on every deploy making sure that things were still okay in production.…</description><pubDate>Sat, 14 Jul 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Once upon a time, I was building my First Serious Rails App. I was drawn to Rails in the first place because of automated testing and ActiveRecord; I felt the pain of not using an ORM and spending about a week on every deploy making sure that things were still okay in production. So of course, I tried to write a pretty reasonable suite of tests for the app.&lt;/p&gt;
&lt;p&gt;To gloss over some details to protect the innocent, this app was a marketplace: some people owned Things, and some people wanted to place Orders. Only certain Things could fulfill an Order, so of course, there was also a ThingType table that handled different types of Things. Of course, some Types came in multiple Sizes, so there also needed to be a Size Table and a ThingTypeSize table so that a User could own a Thing of a certain Type and a certain Size.&lt;/p&gt;
&lt;p&gt;Stating that creating my objects for tests was difficult would be an understatement.&lt;/p&gt;
&lt;p&gt;Then I read a blog post about FactoryGirl. Holy crap! This would basically save me. With one simple &lt;code&gt;Factory(:thing)&lt;/code&gt; I could get it to automatically build a valid list of all that other crap that I needed!&lt;/p&gt;
&lt;p&gt;So of course, I had to write my spec for a thing:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;describe &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Order&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  it &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;generates quotes only from Things that are of the right size&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    order&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Factory&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:order&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    thing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Factory&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:thing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:size&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; order.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    thing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Factory&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:thing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    order.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;quote!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    order.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;quote&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;thing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;should&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; thing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This test worked. It also generated around 15 objects, saved them in the database, and queried them back out. I don’t have the code running anymore, but it was like 30-40 queries, and took a second or two to run.&lt;/p&gt;
&lt;p&gt;That was one test. I was trying to test a lot, even though I wasn’t good at test first yet, so my suite got to be pretty big. Also, sometimes my factories weren’t the best, so I’d spend a day wondering why certain things would start failing. Turns out I’d defined them slightly wrong, validations started to fail, etc.&lt;/p&gt;
&lt;h2 id=&quot;how-did-we-get-here&quot;&gt;How did we get here?&lt;/h2&gt;
&lt;p&gt;This story is one of Ruby groupthink gone awry, basically. Of course, we know that fixtures get complicated. They get complicated because we have these crazy ActiveRecord models, don’t use plain Ruby classes when appropriate, and validations make us make extra objects just to get tests to pass. Then fixtures get out of date. So let’s introduce a pattern!&lt;/p&gt;
&lt;p&gt;Of course, since we know that Factories are really useful when things get complicated, let’s make sure to use them from the start, so we don’t have to worry about them later. Everyone started doing this. Here’s how new Rails apps get started:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ rails new my_app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  README.rdoc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;snip&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  vendor/plugins/.gitkeep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;         run  bundle install&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Fetching gem metadata from https://rubygems.org/.........&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;snip&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Using uglifier (1.2.6) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ cd my_app &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/my_app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ cat &gt;&gt; Gemfile&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;gem &quot;rspec-rails&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;gem &quot;factory_girl_rails&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;^D&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/my_app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ bundle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Fetching gem metadata from https://rubygems.org/........&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;snip&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/my_app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/my_app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ rails g rspec:install                                                   &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  .rspec&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       exist  spec&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create  spec/spec_helper.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ rails g resource foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      invoke  active_record&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create    db/migrate/20120714180554_create_foos.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create    app/models/foo.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      invoke    rspec&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create      spec/models/foo_spec.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      invoke      factory_girl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create        spec/factories/foos.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      invoke  controller&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create    app/controllers/foos_controller.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      invoke    erb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create      app/views/foos&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      invoke    rspec&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create      spec/controllers/foos_controller_spec.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      invoke    helper&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create      app/helpers/foos_helper.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      invoke      rspec&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create        spec/helpers/foos_helper_spec.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      invoke    assets&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      invoke      coffee&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create        app/assets/javascripts/foos.js.coffee&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      invoke      scss&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      create        app/assets/stylesheets/foos.css.scss&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      invoke  resource_route&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       route    resources :foos&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steve at thoth in ~/tmp/my_app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ rake db:migrate                                                         &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;==  CreateFoos: migrating =====================================================&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;-- create_table(:foos)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   -&gt; 0.0065s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;==  CreateFoos: migrated (0.0066s) ============================================&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ cat &gt; spec/models/foo_spec.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;require &apos;spec_helper&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;describe Foo do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  it &quot;does something&quot; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    foo = Factory(:foo)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    foo.something!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;^D&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ bundle exec rake spec       &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;/Users/steve/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec ./spec/controllers/foos_controller_spec.rb ./spec/helpers/foos_helper_spec.rb ./spec/models/foo_spec.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;*DEPRECATION WARNING: Factory(:name) is deprecated; use FactoryGirl.create(:name) instead. (called from block (2 levels) in &amp;#x3C;top (required)&gt; at /Users/steve/tmp/my_app/spec/models/foo_spec.rb:5)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;F&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Pending:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  FoosHelper add some examples to (or delete) /Users/steve/tmp/my_app/spec/helpers/foos_helper_spec.rb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # No reason given&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # ./spec/helpers/foos_helper_spec.rb:14&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Failures:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  1) Foo does something&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     Failure/Error: foo.something!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     NoMethodError:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       undefined method `something!&apos; for #&amp;#x3C;Foo:0x007f82c70c07a0&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     # ./spec/models/foo_spec.rb:6:in `block (2 levels) in &amp;#x3C;top (required)&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Finished in 0.01879 seconds&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;2 examples, 1 failure, 1 pending&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Failed examples:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;rspec ./spec/models/foo_spec.rb:4 # Foo does something&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Randomized with seed 27300&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;rake aborted!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;/Users/steve/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec ./spec/controllers/foos_controller_spec.rb ./spec/helpers/foos_helper_spec.rb ./spec/models/foo_spec.rb failed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Tasks: TOP =&gt; spec&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;(See full trace by running task with --trace)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Woo! Failing test! Super easy. But what about that test time?&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Finished in 0.01879 seconds&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, test time isn’t everything, but a hundredth of a second. Once we hit a hundred tests, we’ll be taking almost two full seconds to run our tests.&lt;/p&gt;
&lt;p&gt;What if we just &lt;code&gt;Foo.new.something!&lt;/code&gt;?&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Finished in 0.00862 seconds&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A whole hundredth of a second faster. A hundred tests now take one second rather than two.&lt;/p&gt;
&lt;p&gt;Of course, once you add more complicated stuff to your factories, your test time goes up. Add a validation that requires an associated model? Now that test runs twice as slow. You didn’t change the test at all! But it got more expensive.&lt;/p&gt;
&lt;p&gt;Now, a few years in, we have these massive, gross, huge, long-running test suites.&lt;/p&gt;
&lt;h2 id=&quot;what-to-do&quot;&gt;What to do?&lt;/h2&gt;
&lt;p&gt;Now, I don’t think that test times are the end-all-be-all of everything. I really enjoyed &lt;a href=&quot;http://gmoeck.github.com/2012/07/09/dont-make-your-code-more-testable.html&quot;&gt;this post&lt;/a&gt; that floated through the web the other day. I think that the ‘fast tests movement’ or whatever (which I am/was a part of) was a branding mistake. The real point wasn’t about fast tests. Fast tests are really nice! But that’s not a strong enough argument alone.&lt;/p&gt;
&lt;p&gt;The point is that we forgot what testing is supposed to help in the first place.&lt;/p&gt;
&lt;h2 id=&quot;back-to-basics-tdd&quot;&gt;Back to basics: TDD&lt;/h2&gt;
&lt;p&gt;A big feature of tests is to give you feedback on your code. Tests and code have a symbiotic relationship. Your tests inform your code. If a test is complicated, your code is complicated. Ultimately, because tests are a client of your code, you can see how easy or hard your code’s interfaces are.&lt;/p&gt;
&lt;p&gt;So, we have a pain in our interface: our objects need several other ones to exist properly. How do we fix that pain?&lt;/p&gt;
&lt;p&gt;The answer that the Rails community has taken for the last few years is ‘sweep it under the rug with factories!’ And that’s why we’re in the state we’re in. One of the reasons that this happened was that FactoryGirl is a pretty damn good implementation of Factories. I do use FactoryGirl (or sometimes Fabrication) in my request specs; once you’re spinning up the whole stack, factories can be really useful. But they’re not useful for actual unit tests. Which I guess is another way to state what I’m saying: we have abandoned unit tests, and now we’re paying the price.&lt;/p&gt;
&lt;p&gt;So that’s what it really boils down to: the convenience of factories has set Rails testing strategies and software design back two years.&lt;/p&gt;
&lt;p&gt;You live and learn.&lt;/p&gt;</content:encoded></item><item><title>How can I contribute to Ruby on Rails?</title><link>https://steveklabnik.com/writing/how-can-i-contribute-to-ruby-on-rails-/</link><guid isPermaLink="true">https://steveklabnik.com/writing/how-can-i-contribute-to-ruby-on-rails-/</guid><description>After RailsConf this year, I joined the Rails Issue Team. This means that I help triage issues that people have filed, try to reproduce errors, and point core team members at ones that are most important. Since doing that, a few people have asked me how to get started, so I…</description><pubDate>Thu, 05 Jul 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;After RailsConf this year, I joined the Rails Issue Team. This means that I help triage issues that people have filed, try to reproduce errors, and point core team members at ones that are most important. Since doing that, a few people have asked me how to get started, so I decided to draw up my thoughts here.&lt;/p&gt;
&lt;p&gt;Note that there is also an &lt;a href=&quot;http://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html&quot;&gt;official Rails Guide on contribution&lt;/a&gt; too.&lt;/p&gt;
&lt;h2 id=&quot;who-helps-with-rails&quot;&gt;Who helps with Rails?&lt;/h2&gt;
&lt;p&gt;First up is the Rails Core team: &lt;a href=&quot;http://rubyonrails.org/core/&quot;&gt;http://rubyonrails.org/core/&lt;/a&gt; Core team members essentially have the authority to merge code into the main Rails codebase. Someone from core reviews every patch that goes into Rails.&lt;/p&gt;
&lt;p&gt;Issues team: This group of people has the authority to tag, close, and edit tickets, but can’t actually merge code.&lt;/p&gt;
&lt;p&gt;Documentation team: A few awesome people contribute by writing documentation rather than just code. Docs are super important, so all these people are also awesome.&lt;/p&gt;
&lt;p&gt;Everyone else!: Rails is open source after all, and 1224 people have contributed at least one patch.&lt;/p&gt;
&lt;p&gt;You can find everyone’s commits and count here: &lt;a href=&quot;http://contributors.rubyonrails.org/&quot;&gt;http://contributors.rubyonrails.org/&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;about-payment&quot;&gt;About payment&lt;/h3&gt;
&lt;p&gt;Nobody is paid to just work on Rails itself. Everyone is a volunteer. Rails runs on a ‘scratch your own itch’ policy. This has two big effects:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Pull requests can sit sometimes. Pull requests must be merged by a Core member, so after your patch is submitted, you’re basically waiting on someone from a group of about 12 to decide ‘hey, I should merge some pull requests today’ and get on it. There are currently 168 pull requests open on Rails, the oldest of which is three months since its last comment.&lt;/li&gt;
&lt;li&gt;Feature requests may simply fall on deaf ears. If you have a suggestion for Rails, and you don’t want to implement it, you need to convince someone to write the code for you. But it’s not as if the core team has a list of requested features that it goes over when working. Of course, they have a list of the features that they want to add, but it’s not like it’s comprehensive from every feature requested. That said, it’s possible that your idea may spark the attention of someone, so sharing a feature request is valuable. But don’t feel entitled here.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;i-found-a-bug-what-should-i-do&quot;&gt;I found a bug, what should I do?&lt;/h2&gt;
&lt;p&gt;File a ticket on the &lt;a href=&quot;https://github.com/rails/rails/issues&quot;&gt;Rails issue tracker&lt;/a&gt; and give us as much information as possible.&lt;/p&gt;
&lt;p&gt;Note that only 3.2 is getting bug fixes. 3.1 and earlier are security fix only.&lt;/p&gt;
&lt;p&gt;Good: Clear bug report, listed versions of Rails and/or Ruby and backtrace if applicable&lt;/p&gt;
&lt;p&gt;Better: Steps to reproduce, maybe with a sample app.&lt;/p&gt;
&lt;p&gt;Best: All of the above with a patch that fixes the problem.&lt;/p&gt;
&lt;h2 id=&quot;ive-found-a-security-vulnerability-what-should-i-do&quot;&gt;I’ve found a security vulnerability, what should I do?&lt;/h2&gt;
&lt;p&gt;Don’t submit something to the tracker. Instead, check out &lt;a href=&quot;http://rubyonrails.org/security&quot;&gt;this page&lt;/a&gt; which outlines the security policy. Basically, send an email to &lt;a href=&quot;mailto:security@rubyonrails.org&quot;&gt;security@rubyonrails.org&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;i-have-a-feature-request-what-should-i-do&quot;&gt;I have a feature request, what should I do?&lt;/h2&gt;
&lt;p&gt;Please don’t file an Issue; it’s a bad medium for discussing these kinds of things. It also makes it harder to keep track of what’s a bug and what’s a wish for future changes. Please post to the &lt;a href=&quot;https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core&quot;&gt;rails-core mailing list&lt;/a&gt; instead. Your idea is much more likely to be seen and discussed there.&lt;/p&gt;
&lt;p&gt;You may get no response from the list. People tend to say nothing if they’re not interested. It happens.&lt;/p&gt;
&lt;h2 id=&quot;i-want-feedback-on-an-idea-before-i-work-up-a-patch&quot;&gt;I want feedback on an idea before I work up a patch&lt;/h2&gt;
&lt;p&gt;Same as a feature request, please ping the &lt;a href=&quot;https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core&quot;&gt;rails-core mailing list&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;ive-written-a-patch-now-what&quot;&gt;I’ve written a patch, now what?&lt;/h2&gt;
&lt;p&gt;Submit a pull request with your patch. Someone from core will review it, and may ask you to modify what you’ve done. Eventually it will either get merged into Rails or rejected.&lt;/p&gt;
&lt;h2 id=&quot;i-want-to-write-docs-now-what&quot;&gt;I want to write docs, now what?&lt;/h2&gt;
&lt;p&gt;Don’t sumbit them as issues to the main Rails repo, instead, check out &lt;a href=&quot;http://weblog.rubyonrails.org/2012/3/7/what-is-docrails/&quot;&gt;docrails&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;i-want-to-help-but-dont-know-what-to-work-on&quot;&gt;I want to help, but don’t know what to work on!&lt;/h2&gt;
&lt;p&gt;We try to tag each issue with the part of Rails it affects. If you don’t know where to get started, pick your favorite part of Rails and sort the issues by that part. For example &lt;a href=&quot;https://github.com/rails/rails/issues?labels=asset+pipeline&amp;#x26;page=1&amp;#x26;sort=updated&amp;#x26;state=open&quot;&gt;here are all the issues relating to the asset pipeline&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Try to reproduce the bug locally, write a test that fails, write a patch, boom!&lt;/p&gt;
&lt;h2 id=&quot;how-do-i-set-up-my-local-machine-to-work-on-rails&quot;&gt;How do I set up my local machine to work on Rails&lt;/h2&gt;
&lt;p&gt;Check the Rails Guide &lt;a href=&quot;http://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#running-the-test-suite&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Shoes 4 work is starting: get involved!</title><link>https://steveklabnik.com/writing/shoes-4-work-is-starting--get-involved/</link><guid isPermaLink="true">https://steveklabnik.com/writing/shoes-4-work-is-starting--get-involved/</guid><description>As you know, I’ve been doing a lot of work over the last few years to keep _why’s Shoes project going. A few other intrepid individuals have been doing a lot as well. We’re starting to work on Shoes 4, and we’d love your help. A little about Shoes If you didn’t know, Shoes is a…</description><pubDate>Fri, 25 May 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As you know, I’ve been doing a lot of work over the last few years to keep _why’s &lt;a href=&quot;http://shoesrb.com/&quot;&gt;Shoes&lt;/a&gt; project going. A few other intrepid individuals have been doing a lot as well. We’re starting to work on Shoes 4, and we’d love your help.&lt;/p&gt;
&lt;h2 id=&quot;a-little-about-shoes&quot;&gt;A little about Shoes&lt;/h2&gt;
&lt;p&gt;If you didn’t know, Shoes is a GUI toolkit for Ruby. It uses blocks heavily:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Shoes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;app&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  para &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Push the button&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  button &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Me! Me!&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    alert &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Good job.&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Super simple. You get native widgets on all platforms.&lt;/p&gt;
&lt;h2 id=&quot;shoes-4&quot;&gt;Shoes 4&lt;/h2&gt;
&lt;p&gt;Shoes 4 is a total re-write of Shoes. It’s being done in JRuby. There are a few related projects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ShoesSpec: An executable specification for Shoes implementations, so that others can co-exist. A few other Shoes projects exist already, and a unified interface will be great.&lt;/li&gt;
&lt;li&gt;Shoes-mocks: Sort of the opposite, a dummy set of Shoes that you can use to test applications written in Shoes.&lt;/li&gt;
&lt;li&gt;The website: A new website is being made as well. Help here would be just as awesome as work on Shoes itself.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-we-need&quot;&gt;What we need&lt;/h2&gt;
&lt;p&gt;Of course, pull requests are always welcome. But if you use Shoes or want to, please get involved in &lt;a href=&quot;http://github.com/shoes/shoes4/issues&quot;&gt;the discussions&lt;/a&gt; about what Shoes 4 will look like on the bug tracker. Feel free to open an Issue with any topic for discussion. Thoughts from users, current and potential, are always awesome!&lt;/p&gt;
&lt;p&gt;Let’s all have fun developing Shoes 4!&lt;/p&gt;</content:encoded></item><item><title>Building StoreEngine</title><link>https://steveklabnik.com/writing/building-storeengine/</link><guid isPermaLink="true">https://steveklabnik.com/writing/building-storeengine/</guid><description>So I said I was gonna build antisocialne.ws. But I’m changing gears instead: I’d rather do this project, which has a better spec and needs a reference implementation. Building StoreEngine from Steve Klabnik on Vimeo .</description><pubDate>Thu, 05 Apr 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;So I said I was gonna build antisocialne.ws. But I’m changing gears instead: I’d rather do this project, which has a better spec and needs a reference implementation.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://vimeo.com/39850969&quot;&gt;Building StoreEngine&lt;/a&gt; from &lt;a href=&quot;http://vimeo.com/steveklabnik&quot;&gt;Steve Klabnik&lt;/a&gt; on &lt;a href=&quot;http://vimeo.com/&quot;&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Introducing metadown</title><link>https://steveklabnik.com/writing/introducing-metadown/</link><guid isPermaLink="true">https://steveklabnik.com/writing/introducing-metadown/</guid><description>Because I don’t have enough gems made already, I made another one last night: metadown . What’s Metadown do? This blog originally used Jekyll. When I moved it to my own personal blog implementation, I noticed something: Markdown doesn’t actually have support for adding YAML at…</description><pubDate>Mon, 23 Jan 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Because I don’t have enough gems made already, I made another one last night: &lt;a href=&quot;https://rubygems.org/gems/metadown&quot;&gt;metadown&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;whats-metadown-do&quot;&gt;What’s Metadown do?&lt;/h2&gt;
&lt;p&gt;This blog originally used Jekyll. When I moved it to my own personal blog implementation, I noticed something: Markdown doesn’t actually have support for adding YAML at the top of your files, like Jekyll does. I always &lt;em&gt;knew&lt;/em&gt; this, I just didn’t think about it before. And I love using Markdown, so I ended up extracting my own version of this trick into Metadown.&lt;/p&gt;
&lt;p&gt;Basically, sometimes you need metadata about your markup file. YAML is a nice format for writing key/value pairs, lists, and other things… so I’ve let you smash the two of them together in one file by adding some &lt;code&gt;---&lt;/code&gt;s at the top.&lt;/p&gt;
&lt;h2 id=&quot;gimme-an-example&quot;&gt;Gimme an Example&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;require &apos;metadown&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;data = Metadown.render(&quot;hello world&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;data.output #=&gt; &quot;&amp;#x3C;p&gt;hello, world&amp;#x3C;/p&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;data.metadata #=&gt; &quot;{}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;text = &amp;#x3C;&amp;#x3C;-MARKDOWN&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;key: &quot;value&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;hello world&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;MARKDOWN&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;data = Metadown.render(text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;data.output #=&gt; &quot;&amp;#x3C;p&gt;hello, world&amp;#x3C;/p&gt;\n&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;data.metadata #=&gt; {&quot;key&quot; =&gt; &quot;value&quot;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;wheres-the-code&quot;&gt;Where’s the code?&lt;/h2&gt;
&lt;p&gt;It’s implemented using a custom parser for Redcarpet, has a test suite, and works on every Ruby that’s not JRuby. You can &lt;a href=&quot;https://github.com/steveklabnik/metadown&quot;&gt;check out the source here&lt;/a&gt;. Issues and Pull Requests welcome. There’s at least one thing that I know I’ll need to add to it in the near future.&lt;/p&gt;</content:encoded></item><item><title>Moving from Sinatra to Rails</title><link>https://steveklabnik.com/writing/moving-from-sinatra-to-rails/</link><guid isPermaLink="true">https://steveklabnik.com/writing/moving-from-sinatra-to-rails/</guid><description>I love both Sinatra and Rails, for different reasons. I’ve heard a few different heuristics for which framework would be better for your application, but I’m not sure the answer is all that simple, really. Regardless of which is correct for your application, I haven’t seen a lot…</description><pubDate>Tue, 17 Jan 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I love both Sinatra and Rails, for different reasons. I’ve heard a few different heuristics for which framework would be better for your application, but I’m not sure the answer is all that simple, really. Regardless of which is correct for your application, I haven’t seen a lot of people discussing how to move between the two frameworks.&lt;/p&gt;
&lt;h2 id=&quot;step-one-evaluate-your-test-coverage&quot;&gt;Step One: Evaluate your test coverage&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;http://www.amazon.com/gp/product/0131177052/ref=as_li_ss_tl?ie=UTF8&amp;#x26;tag=stesblo026-20&amp;#x26;linkCode=as2&amp;#x26;camp=1789&amp;#x26;creative=390957&amp;#x26;creativeASIN=0131177052&quot;&gt;Working Effectively with Legacy Code&lt;/a&gt; (this is an affiliate link. Does this bother you?), Michael Feathers introduces a fantastic technique called “Lean on the Compiler.” It’s on page 315, for those of you playing along at home.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The primary purpose of a compiler is to translate source code into some other form, but in statically typed languages, you can do much more with a compiler. You can take advantage of its type checking and use it to identify which changes you need to make. I call this practice Leaning on the Compiler.Lean on the Compiler is a powerful technique, but you have to know what its limits are; if you don’t, you can end up making some serious mistakes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now, in a language like Ruby, we don’t have type checking. We do have something that double checks our code correctness: tests. Just like static type checks, tests cannot &lt;em&gt;ensure&lt;/em&gt; that you’ve done your transformations, but they sure as hell can help. This becomes step one in the effort to move from one framework to another: evaluate your test coverage.&lt;/p&gt;
&lt;h3 id=&quot;acceptance-tests-are-most-important&quot;&gt;Acceptance Tests are most important&lt;/h3&gt;
&lt;p&gt;When looking at your tests, first check out your acceptance tests. These are the most important, for two reasons: they’re abstracted away from the framework itself, and their purpose in life is to make sure that major functionality is working. Do you have your happy paths covered? Is there any major functionality that’s &lt;em&gt;not&lt;/em&gt; covered by acceptance tests?&lt;/p&gt;
&lt;p&gt;While the happy path is a big deal, when moving to a new framework, we’re going to introduce a high chance of people encountering issues, so the sad path is also important. I personally tend to not write very many sad path acceptance tests and leave that for tests at the lower level. This is a good time to take stock of the worst of your worst paths: is there certain functionality that’s &lt;em&gt;absolutely&lt;/em&gt; important to be handled 100% correctly? Then write some new acceptance tests. As with any kind of engineering project, there’s a tradeoff here: you can’t get coverage of every possible situation. Tests are supposed to give you confidence in your code, so liberally add coverage for any situation that makes you nervous.&lt;/p&gt;
&lt;h3 id=&quot;integration-tests-are-important-too&quot;&gt;Integration tests are important too&lt;/h3&gt;
&lt;p&gt;These tests are a bit more tricky, as they are tied into the framework that you’re using. I’m not sure that anyone writes many of these kinds of tests with Sinatra, outside of maybe model to model integration tests.&lt;/p&gt;
&lt;h3 id=&quot;model-and-view-tests-not-a-big-deal&quot;&gt;Model and View tests: not a big deal&lt;/h3&gt;
&lt;p&gt;These kinds of tests are much more of a sanity check than anything else for the purposes of this kind of move. It’s good that they pass, but really, they shouldn’t be too reliant on the framework you’re using. They’re better for making sure you’ve put things in the correct directories and haven’t forgotten anything in the move.&lt;/p&gt;
&lt;p&gt;I’m not even sure what a ‘view test’ would be in Sinatra, and they tend to be not in favor with Rails projects anyway, so that’s more of a general ‘framework to framework’ bit of advice than anything else.&lt;/p&gt;
&lt;h3 id=&quot;controllers-dont-exist-in-sinatra&quot;&gt;Controllers don’t exist in Sinatra…&lt;/h3&gt;
&lt;p&gt;… so you don’t really write those kinds of tests. Controller tests don’t seem to be that popular in Rails-land these days either.&lt;/p&gt;
&lt;h2 id=&quot;step-two-git-can-help&quot;&gt;Step Two: Git Can help&lt;/h2&gt;
&lt;p&gt;I’ll show you how I managed transitioning files over. However, I’m really interested in the idea of using a &lt;a href=&quot;http://help.github.com/subtree-merge/&quot;&gt;subtree merge&lt;/a&gt; to keep being able to update the original Sinatra project while working on the new Rails project.&lt;/p&gt;
&lt;p&gt;First step is, of course, make a new branch. This transition will probably take some time, and you may want to push hotfixes into production during that period. Using master is not advised.&lt;/p&gt;
&lt;p&gt;Next, make a copy of everything and shove it in a temp directory. Then delete everything in the git repo (except the .git directory, of course) and commit that blank slate. Back up one directory above your project directory, run &lt;code&gt;rails new myproject&lt;/code&gt; with your project’s name, and you’ll get a blank rails app. &lt;code&gt;cd myproject&lt;/code&gt; and &lt;code&gt;mkdir sinatra&lt;/code&gt;, then copy the backup you made from the temp directory into the sinatra directory. Finally, commit this.&lt;/p&gt;
&lt;p&gt;Now you’ve got a new blank Rails app with all your old code in a directory, and you can start moving things over.&lt;/p&gt;
&lt;h2 id=&quot;step-three-set-up-your-test-harness&quot;&gt;Step Three: Set up your test harness&lt;/h2&gt;
&lt;p&gt;Since we’re going to allow our tests to guide our move, it pays to get tests up and running first! Depending on what testing framework you use, get it going with Rails. In our case, we were using minitest to test our code. This took a little bit of effort to get working with Rails, but there weren’t a ton of problems.&lt;/p&gt;
&lt;p&gt;As always: red, green, refactor. I’d make a simple test that doesn’t test anything, &lt;code&gt;assert true&lt;/code&gt;. Make sure that your &lt;code&gt;rake test&lt;/code&gt; or &lt;code&gt;rspec .&lt;/code&gt; or whatever you’ll use to run the tests works and then remove the dummy test.&lt;/p&gt;
&lt;p&gt;There are two strategies for moving tests over: you can move a chunk at a time or move one at a time. Chunks are easier, but then you get commits where the build is broken. It’s really up to you and your team’s tastes: a huge test suite with a number of failures can show you how close you are to being done with the first 90% of the work. And since you’re not planning on releasing in this half-finished state, having a broken build is not &lt;em&gt;that&lt;/em&gt; terrible… As always, you’re the professional: make the call.&lt;/p&gt;
&lt;h2 id=&quot;step-four-move-your-models&quot;&gt;Step Four: Move your models&lt;/h2&gt;
&lt;p&gt;Since models are the simplest to move, I like to do them first. You &lt;em&gt;should&lt;/em&gt; just be able to copy over each test file and model file, though because you were using Sinatra, your models may be all in one file. This step should be largely painless, though: you’re not really relying on any framework-specific things.&lt;/p&gt;
&lt;p&gt;Model tests can still suss out problems with your environment, though, like incorrect database settings, certain environment variables…&lt;/p&gt;
&lt;p&gt;The idea to begin with the easiest thing comes from &lt;a href=&quot;http://www.daveramsey.com/home/&quot;&gt;Dave Ramsey&lt;/a&gt;, oddly enough. My aunt works at a bank, and when I went to college, she bought me a few of his books to help me learn about personal finance. Dave is a big fan of the ‘get rid of all debt’ school of thought, and so a large portion of his work is strategies for getting out of debt. Dave contends that paying off loans with the highest interest, while mathematically the fastest way to pay off your obligations, is not actually the best strategy. People like to see progress and are heartened by seeing it. By paying off the smallest loan first, one is much more likely to feel more positive about the headway one is making, and so it’s a much better strategy in the end.&lt;/p&gt;
&lt;p&gt;The same logic applies with this move: why start with the hard stuff? Knock out some quick wins to keep your spirits high.&lt;/p&gt;
&lt;h2 id=&quot;step-five-convert-your-controllers&quot;&gt;Step Five: Convert your controllers&lt;/h2&gt;
&lt;p&gt;Next up: get your controllers created. This is a pretty manual process:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;get &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;foos&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  @foos &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Foo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;all&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  render &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:&quot;foos/index&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;becomes&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; FooController&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ApplicationController&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; index&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @foos &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Foo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;all&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The biggest issue with moving all of this stuff is that Sinatra and Rails use &lt;code&gt;redirect&lt;/code&gt; and &lt;code&gt;redirect_to&lt;/code&gt;, respectively. So you’ll have to convert that stuff. However, I wouldn’t recommend changing things like &lt;code&gt;redirect &quot;/foos/#{id}&quot;&lt;/code&gt; to &lt;code&gt;redirect_to foo_path(foo)&lt;/code&gt; just yet. When dealing with legacy code, you want to change as little as possible with each step so that you know when you have introduced an error. If you try to convert things to a Rails style as well, you run the risk of introducing errors. Therefore, in all of these moves, leave the hell enough alone as much as possible. Once your code is up and running, you can gladly refactor. Just don’t do it now.&lt;/p&gt;
&lt;p&gt;Don’t forget to generate your routes, too. Sinatra’s DSL is like a combination of Rails’ routing and controllers. Set those up in this step as well.&lt;/p&gt;
&lt;p&gt;Since we don’t have tests, this part is very error-prone. Luckily, our acceptance tests will catch these issues in step seven. So give it your best shot, but don’t worry about being 100% perfect. Focus on getting the basic structural changes in place.&lt;/p&gt;
&lt;p&gt;Having tests is so nice. :/&lt;/p&gt;
&lt;h2 id=&quot;step-six-move-your-views&quot;&gt;Step Six: Move your views&lt;/h2&gt;
&lt;p&gt;This should be as simple as the models: put your views in the correct directory, and things should be golden. If you were using inline views with Sinatra, well, you shouldn’t have that many of them, so breaking them out should be pretty easy.&lt;/p&gt;
&lt;h2 id=&quot;step-seven-listen-to-your-tests&quot;&gt;Step Seven: Listen to your tests&lt;/h2&gt;
&lt;p&gt;Okay! Those last moves were really awkward since we didn’t have tests to check our work. This is where the acceptance tests come in. You can move these over in batches or one at a time, but the acceptance tests will tell you where you forgot a route, if your view is missing, or if you left some little bit of Sinatra-ness in your Rails somewhere.&lt;/p&gt;
&lt;p&gt;You’re almost home! Once you get all your acceptance tests working, you should pat yourself on the back! You’re not done yet, but you’ve made a lot of progress.&lt;/p&gt;
&lt;h2 id=&quot;step-eight-track-your-exceptions&quot;&gt;Step Eight: Track your exceptions!&lt;/h2&gt;
&lt;p&gt;You should have been doing this anyway, but if you weren’t, set up some sort of mechanism to catch and handle exceptions. &lt;a href=&quot;http://airbrakeapp.com/pages/home&quot;&gt;Airbrake&lt;/a&gt; is one such service, but even just recording them yourself would be fine. You &lt;em&gt;need&lt;/em&gt; to have this set up in some form, as you’re likely to generate errors, and examining your exceptions is the best way to track down actual problems.&lt;/p&gt;
&lt;h2 id=&quot;step-nine-plan-out-deployment-strategies&quot;&gt;Step Nine: Plan out deployment strategies&lt;/h2&gt;
&lt;p&gt;Of course, now that you’re done developing, it’s time to get the app out to users. This’ll require a comprehensive plan for actually making the jump. A little bit of foresight can go a long way here.&lt;/p&gt;
&lt;p&gt;My strategy was to roll out the new Rails app under a new domain: &lt;a href=&quot;http://beta.myapp.com/&quot;&gt;http://beta.myapp.com/&lt;/a&gt;. I then pinged my users with a message along the lines of “We’ve made some infrastructure updates, if you’d like to help us test them out, visit the beta site.”&lt;/p&gt;
&lt;p&gt;This approach does have some sticky points, however. The first one is the database. In my case, I had a high level of confidence in my code, and this application wasn’t for anything that was considered mission-critical. We also had a decent backup strategy in place. Therefore, I connected the beta site up to the production data store. This meant there were no migration issues later. However, this may make you uncomfortable, but there are other options, too. You can treat the beta as a sandbox, and tell people that the data will not be persisted after the beta, or you can migrate people’s data back to the production data store afterwards.&lt;/p&gt;
&lt;p&gt;Another approach is to automatically migrate a portion of your users over to the new code base. Ideally, nobody notices: your code base shouldn’t have changed in looks or functionality.&lt;/p&gt;
&lt;h2 id=&quot;step-ten-push-to-production&quot;&gt;Step Ten: Push to production!&lt;/h2&gt;
&lt;p&gt;Congrats! Execute on the plan you created in step nine, and get ready to answer tons of emails about why your app is broken! Just kidding, I hope! I really recommend the beta strategy for this reason. No plan survives first contact with the enemy. Your users &lt;em&gt;will&lt;/em&gt; find things you didn’t, no matter how much manual testing you did along the way.&lt;/p&gt;
&lt;h2 id=&quot;another-strategy-mounting&quot;&gt;Another strategy: mounting&lt;/h2&gt;
&lt;p&gt;I haven’t actually tried this myself, but I’ve been thinking about another way to make this happen: mount your Sinatra app inside of a Rails app, and use that to move things over slowly. &lt;a href=&quot;http://stackoverflow.com/a/6972706&quot;&gt;Here’s an example&lt;/a&gt; of how to make this happen technically. If you had a really big Sinatra application, I could see how this might get you deploying faster; just carve out one vertical chunk of your app, move it over, and keep the rest of your app running in Sinatra.&lt;/p&gt;</content:encoded></item><item><title>ActiveRecord considered harmful</title><link>https://steveklabnik.com/writing/active-record-considered-harmful/</link><guid isPermaLink="true">https://steveklabnik.com/writing/active-record-considered-harmful/</guid><description>It is practically impossible to teach OO design to students that have had a prior exposure to Rails: as potential programmers they are mentally mutilated beyond hope of regeneration.Edsger W. Dijkstra (paraphrased) I love ActiveRecord. It was the first ORM I’d ever interacted…</description><pubDate>Fri, 30 Dec 2011 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;It is practically impossible to teach OO design to students that have had a prior exposure to Rails: as potential programmers they are mentally mutilated beyond hope of regeneration.Edsger W. Dijkstra (paraphrased)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I love ActiveRecord. It was the first ORM I’d ever interacted with. My first technical employer had commissioned a DBA, and so of course, we wrote all our own queries. Which was fine; I know my way around a JOIN or two. The problem came when it was time to make a new class; time to write “SELECT * FROM ‘tableName’ WHERE ‘id’=‘%’”… for each class. “Just copy one of the other small classes, hack out everything, and change the table names,” were my instructions. Fine. Whatever. But I knew there had to be a better way…&lt;/p&gt;
&lt;p&gt;Along comes Rails. Holy crap, ActiveRecord is &lt;em&gt;awesome&lt;/em&gt;! It writes the &lt;em&gt;exact&lt;/em&gt; SQL I would have written myself! I don’t need to do &lt;em&gt;anything&lt;/em&gt;. This is the best thing since sliced bread. But years later, not everything is rainbows and sunshine. I’ve written a &lt;em&gt;lot&lt;/em&gt; of crappy code, and most of it is due to following Rails ‘best practices.’ Which is totally fine! Rails is kinda getting old these days. It’s no longer the new and shiny. But while Rails developers have gotten really good at busting out little CRUD apps, we haven’t moved web application design &lt;em&gt;forward&lt;/em&gt; in a really, really long time.&lt;/p&gt;
&lt;p&gt;And that’s what Rails did, really. That fifteen minute blog video was shocking. I know several people that threw away two or three week old projects and re-built their stuff in Rails within moments of watching it. And Rails has continued to lead the way in improving how we build rich applications on the web; the (not so but kinda whatever nobody but me cares) RESTful routing was great. The asset pipeline, though it has some bugs, has been great. The obsession with DRY has been great. The test obsession has been great. But Rails has also not been great in aiding us in writing maintainable software. Many of Rails’ design decisions make it difficult to write &lt;em&gt;great&lt;/em&gt; software. It helps us write good software, but that isn’t enough anymore.&lt;/p&gt;
&lt;p&gt;The real problem is that to truly move forward, Rails will have to re-invent itself, and I’m not sure that it can.&lt;/p&gt;
&lt;h2 id=&quot;activerecord-is-the-problem&quot;&gt;ActiveRecord is the problem&lt;/h2&gt;
&lt;p&gt;I’m not going to talk about all of the problems Rails has today, but I’d like to show you the biggest, most central one: ActiveRecord.&lt;/p&gt;
&lt;p&gt;ActiveRecord’s greatest strength is also its problem: Tying class names to table names. This means that it’s impossible to de-couple your persistence mechanism from your domain logic. You can manage it through a combination of &lt;code&gt;set_table_name&lt;/code&gt;, making a bunch of &lt;code&gt;Repository&lt;/code&gt; classes, and careful coding… but then you might as well be using DataMapper. Except the Ruby library of the same name doesn’t really implement the DataMapper pattern all that well either, having the same issue of tying it all together.&lt;/p&gt;
&lt;p&gt;This has another interesting effect: it led directly to the ‘fat model’ recommendation. While ‘get your stuff out of the controller’ is correct, it’s lead Rails developers to build huge, monolithic models that are hard to test, and violate SRP. It took me two and a half years to realize that Ruby classes in the models folder don’t have to inherit from &lt;code&gt;ActiveRecord::Base&lt;/code&gt;. That is a problem.&lt;/p&gt;
&lt;p&gt;We’ve gotten into a situation with a local minimum: our quest for great software has lead us to DRY ourselves into a corner. Now we have code that’s incredibly tightly coupled. Our ‘single responsibility’ is ‘anything and everything that tangentially relates to a Post.’&lt;/p&gt;
&lt;h2 id=&quot;actioncontroller-is-the-problem&quot;&gt;ActionController is the problem&lt;/h2&gt;
&lt;p&gt;ActionController relies on instance variables to pass information from the controller to the view. Have you ever seen a 200 line long controller method? I have. Good luck teasing out which instance variables actually get set over the course of all those nested &lt;code&gt;if&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;The whole idea is kinda crazy: Yeah, it looks nice, but we literally just say ‘increase the scope of variables to pass data around.’ If I wrote a post saying “Don’t pass arguments to methods, just promote your data to a global” I’d be crucified. Yet we do the same thing (albeit on a smaller scale) every time we write a Rails application.&lt;/p&gt;
&lt;h2 id=&quot;actionview-is-the-problem&quot;&gt;ActionView is the problem&lt;/h2&gt;
&lt;p&gt;The whole idea of logic in templates leads to all kinds of problems. They’re hard to test, they’re hard to read, and it’s not just a slippery slope, but a steep one. Things go downhill &lt;em&gt;rapidly&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;What I’d really like to see is Rails adopting a ‘ViewModel + templates’ system, with logic-less templates and presenter-esque models that represent the views. The differences between Django’s idea of ‘views’ and Rails’ idea of ‘views’ are interesting here.&lt;/p&gt;
&lt;h2 id=&quot;mvc-is-the-problem&quot;&gt;MVC is the problem&lt;/h2&gt;
&lt;p&gt;If you’ll notice, I basically have said that models are a problem. Controllers are a problem. Views are a problem. MVC has served the web well, even if it isn’t the GUI style MVC that named the pattern. But I think we’re reaching its limits; the impedance mismatch between HTTP and MVC, for example, is pretty huge. There are other ways to build web applications; I’m particularly excited about &lt;a href=&quot;http://rubyconf-webmachine.heroku.com/&quot;&gt;WebMachine&lt;/a&gt;. I don’t have a constructive alternative to offer here, I just know there’s a problem. I’m still mulling this one over.&lt;/p&gt;
&lt;h2 id=&quot;its-still-good-even-with-problems&quot;&gt;It’s still good, even with problems&lt;/h2&gt;
&lt;p&gt;I love Rails. I build software with it daily. Even with its flaws, it’s been a massive success. But because I love Rails, I feel like I can give it straightforward criticism: it’s easier to trash something you love. The real issue is that changing these things would require some really serious changes. It’d involve re-architecting large portions of things that people classically identify with Rails, and I’m not sure that Rails wants to or can do that.&lt;/p&gt;
&lt;p&gt;This post is light on examples. I want this to be the &lt;em&gt;starting point&lt;/em&gt; of a discussion, not the end of it. Expect more, in detail, from me in the future. What do you think? Are these problems pain points for you? Are they worth fixing? Are they actually problems?&lt;/p&gt;</content:encoded></item><item><title>Redcarpet is awesome</title><link>https://steveklabnik.com/writing/redcarpet-is-awesome/</link><guid isPermaLink="true">https://steveklabnik.com/writing/redcarpet-is-awesome/</guid><description>It’s true. If you haven’t used it yet, Redcarpet is the Markdown parser that GitHub uses to work all that magic on their site. So of course, it’s awesome. You can use it and abuse it What makes it really awesome is the custom renderers feature. Here’s the one from the…</description><pubDate>Wed, 21 Dec 2011 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;It’s true.&lt;/p&gt;
&lt;p&gt;If you haven’t used it yet, &lt;a href=&quot;https://github.com/tanoku/redcarpet&quot;&gt;Redcarpet&lt;/a&gt; is the Markdown parser that &lt;a href=&quot;https://github.com/blog/832-rolling-out-the-redcarpet&quot;&gt;GitHub uses&lt;/a&gt; to work all that magic on their site. So of course, it’s awesome.&lt;/p&gt;
&lt;h2 id=&quot;you-can-use-it-and-abuse-it&quot;&gt;You can use it and abuse it&lt;/h2&gt;
&lt;p&gt;What makes it &lt;em&gt;really&lt;/em&gt; awesome is the custom renderers feature. Here’s the one from the documentation:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# create a custom renderer that allows highlighting of code blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; HTMLwithAlbino&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Redcarpet::Render::HTML&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; block_code&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(code, language)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    Albino&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;safe_colorize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(code, language)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;markdown&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Redcarpet&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Markdown&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;HTMLwithAlbino&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can guess what that does: uses some library called Albino to render code blocks. There are a whole bunch of hooks you can use to make a custom renderer. They make it super easy to do something neat with markdown.&lt;/p&gt;
&lt;p&gt;So I did.&lt;/p&gt;
&lt;h2 id=&quot;check-it-outline-generation&quot;&gt;Check it: outline generation&lt;/h2&gt;
&lt;p&gt;I’m working on… this project. And it needs to render a bunch of articles that are Markdown files. There will be a sidebar. I want to have links to each section. But I’m a good programmer, which means I’m lazy. So why bother making my own sidebar? Especially when I can abuse Redcarpet to do it.&lt;/p&gt;
&lt;p&gt;Oh, and disclaimer: normally, I’m all about super clean code. Last night, that wasn’t the mood I was in. This code is probably terrible. That’s part of the fun! Please feel free to {clean up,obfuscate,golf,unit test} this code, &lt;a href=&quot;mailto:steve@steveklabnik.com&quot;&gt;email me&lt;/a&gt;, and tell me how awesome you are.&lt;/p&gt;
&lt;p&gt;With that disclaimer out of the way, round one:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; OutlineRenderer&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Redcarpet::Render::HTML&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  attr_accessor&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; :outline&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @outline &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    super&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; header&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(text, header_level)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    text_slug&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; text.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;gsub&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D;font-weight:bold&quot;&gt;\W&lt;/span&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;_&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;downcase&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;outline&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [header_level, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&amp;#x3C;a href=&apos;#&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{text_slug}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{text}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;#x3C;/a&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;&amp;#x3C;h&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{header_level}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; id=&apos;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{text_slug}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{text}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;#x3C;/h&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{header_level}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Every time we hit a header, Redcarpet gives us the text and the header level. We grab the text, turn it into a slug, and then append a two-element array to our outline. It keeps track of the level of this header, and makes a link from the slug. Then, we spit out a header tag, adding on an &lt;code&gt;id&lt;/code&gt; element that we linked to in our link.&lt;/p&gt;
&lt;p&gt;Next up, rendering:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;renderer&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; OutlineRenderer&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Redcarpet&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Markdown&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(renderer)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;content&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; r.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;render&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(some_content)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;outline&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; renderer.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;outline&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This instantiates our Renderer, creates our Markdown parser, and renders the content. We also grab the outline we made. Sweet.&lt;/p&gt;
&lt;p&gt;Finally, rendering the outline:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; format_outline&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(outline)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  prev_level&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &quot;&amp;#x3C;ul&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; outline.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;inject&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; |html, data|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    level, link &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; prev_level &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; level&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      html&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&amp;#x3C;ul&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    elsif&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; prev_level &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; level&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      html&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&amp;#x3C;/ul&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    prev_level&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; level&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    html&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&amp;#x3C;li&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{link}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;#x3C;/li&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&amp;#x3C;/ul&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This… is amazing. And terrible. Don’t drink scotch and code, kids. Or do, whatever. This takes our &lt;code&gt;Array&lt;/code&gt; of &lt;code&gt;Array&lt;/code&gt;s that we made with our renderer and runs &lt;code&gt;inject&lt;/code&gt; over it. If our previous level is less than the new level, we indent with a &lt;code&gt;&amp;#x3C;ul&gt;&lt;/code&gt;, and if it’s greater, we outdent with a &lt;code&gt;&amp;#x3C;/ul&gt;&lt;/code&gt;. Then we render our link, and wrap the whole thing in its own set of &lt;code&gt;&amp;#x3C;ul&gt;&lt;/code&gt;s. Done!&lt;/p&gt;
&lt;p&gt;We can call this helper method in our layout, and bam! We get automatic outlines generated for our Markdown files. Like I said, this is quick and dirty, but for a first pass, I don’t feel too bad about it. Get it done, and then get it done right.&lt;/p&gt;</content:encoded></item><item><title>Fast Rails tests with CanCan</title><link>https://steveklabnik.com/writing/fast-rails-tests-with-cancan/</link><guid isPermaLink="true">https://steveklabnik.com/writing/fast-rails-tests-with-cancan/</guid><description>If you haven’t used it, CanCan is a great library for Rails that handles authorization for you. Its calling card is simplicity; just do this: class Ability include CanCan :: Ability def initialize (user) user ||= User . new if user. is? :paying_customer can :show , Article else…</description><pubDate>Mon, 12 Dec 2011 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you haven’t used it, &lt;a href=&quot;https://github.com/ryanb/cancan&quot;&gt;CanCan&lt;/a&gt; is a great library for Rails that handles authorization for you. Its calling card is simplicity; just do this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Ability&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  include&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; CanCan&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Ability&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(user)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    user&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ||=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; User&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; user.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;is?&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; :paying_customer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      can &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Article&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      can &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:free&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      cannot &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:free&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then in a controller:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; show&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  @article &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;find&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(params[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  authorize! &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:read&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, @article&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Super simple! However, as simple as CanCan is, if you want to keep your test times super low, there’s a few things that you should know about.&lt;/p&gt;
&lt;h2 id=&quot;incidental-coupling-the-silent-killer&quot;&gt;Incidental coupling: the silent killer&lt;/h2&gt;
&lt;p&gt;The biggest problem with CanCan from the Fast Tests perspective is that we’ve got coupling with class names. In order to test our Ability class, we also have to load User and Article. Let’s try it without concern for how isolated our tests are:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;cancan/matchers&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;spec_helper&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;describe &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Ability&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:subject&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Ability&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(user) }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:free_article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:free&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:paid_article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:free&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  context &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;random people&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:user&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    it &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;can see free Articles&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      subject.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;can?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, free_article).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;should&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; be_true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    it &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;cannot see non-free Articles&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      subject.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;can?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, paid_article).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;should&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; be_false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  context &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;paying users&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:user&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      User&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;tap&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; |u|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        u.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;roles&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; :paying_customer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    it &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;can see free Articles&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      subject.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;can?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, free_article).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;should&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; be_true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    it &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;can see non-free Articles&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      subject.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;can?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, paid_article).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;should&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; be_true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A few notes about testing with CanCan: I like to organize them with contexts for the different kinds of users, and then what their abilities are below. It gives you a really nice way of setting up those &lt;code&gt;let&lt;/code&gt; blocks, and our tests read real nicely.&lt;/p&gt;
&lt;p&gt;Anyway, so yeah. This loads up all of our models, connects to the DB, etc. This is unfortunate. It’d be nice if we didn’t have to load up &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;Article&lt;/code&gt;. Unfortunately, there’s no real way around it in our &lt;code&gt;Ability&lt;/code&gt;, I mean, if you want them to read all Articles, you have to pass in &lt;code&gt;Article&lt;/code&gt;… hmm. What about this?&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:free_article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;double&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:free&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:paid_article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;double&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:free&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Turns out this works just as well. CanCan reflects on the class that you pass in, so if we just give our double the right class, it’s all gravy. Now we’re not loading &lt;code&gt;Article&lt;/code&gt;, but what about &lt;code&gt;User&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;The key is in the &lt;code&gt;||=&lt;/code&gt;. If we pass in a &lt;code&gt;User&lt;/code&gt;, we won’t call &lt;code&gt;User.new&lt;/code&gt;. So let’s stub that:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:user&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;double&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:is?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:user&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  double.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;tap&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; |u| &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#tap not strictly needed in this example, but if you want multiple roles...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    u.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;stub&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:is?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;with&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:paying_customer&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;and_return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sweet! The first one is a random user: all their &lt;code&gt;is?&lt;/code&gt; calls should be false. The second is our user who’s paid up; we need to stub out their role properly, but that’s about it.&lt;/p&gt;
&lt;h2 id=&quot;its-that-easy&quot;&gt;It’s that easy&lt;/h2&gt;
&lt;p&gt;With some dillegence, isolating your tests isn’t hard, and works really well. I have a few more tests in the example I took this from, and 14 examples still take about a third of a second. Not too shabby!&lt;/p&gt;
&lt;p&gt;Happy authorizing!&lt;/p&gt;
&lt;p&gt;Oh, and the final spec, for reference:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;cancan/matchers&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;app/models/ability&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;describe &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Ability&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:subject&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Ability&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(user) }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:free_article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;double&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:free&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ) }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:paid_article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;double&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:free&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  context &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;random people&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:user&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;double&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:is?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    it &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;can see free Articles&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      subject.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;can?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, free_article).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;should&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; be_true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    it &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;cannot see non-free Articles&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      subject.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;can?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, paid_article).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;should&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; be_false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  context &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;users&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:user&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      double.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;tap&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; |u|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        u.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;stub&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:is?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;with&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:user&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;and_return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    it &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;can see free Articles&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      subject.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;can?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, free_article).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;should&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; be_true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    it &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;can see non-free Articles&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      subject.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;can?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, paid_article).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;should&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; be_true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content:encoded></item><item><title>Devise: ActionController::RoutingError (No Route Matches [GET] /users/sign_out)</title><link>https://steveklabnik.com/writing/devise-actioncontroller-routingerror-no-route-matches-get-slash-users-slash-sign-out/</link><guid isPermaLink="true">https://steveklabnik.com/writing/devise-actioncontroller-routingerror-no-route-matches-get-slash-users-slash-sign-out/</guid><description>Just a quick note about Devise, and its RESTful implications. I ran across this error today, and thought I’d share. I was trying to log out, so I hit the normal route for such things with my browser. Here’s the error: Devise: ActionController::RoutingError (No Route Matches [GET]…</description><pubDate>Sun, 11 Dec 2011 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Just a quick note about Devise, and its RESTful implications. I ran across this error today, and thought I’d share.&lt;/p&gt;
&lt;p&gt;I was trying to log out, so I hit the normal route for such things with my browser. Here’s the error:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Devise: ActionController::RoutingError (No Route Matches [GET] /users/sign_out)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Uhhhhh what? I run rake routes…&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ rake routes | grep destroy_user&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    destroy_user_session DELETE /users/sign_out(.:format)      {:action=&gt;&quot;destroy&quot;, :controller=&gt;&quot;devise/sessions&quot;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, wtf? Well, there is that pesky &lt;code&gt;DELETE&lt;/code&gt;… Googling for this error led me to &lt;a href=&quot;https://github.com/plataformatec/devise/commit/f3385e96abf50e80d2ae282e1fb9bdad87a83d3c&quot;&gt;this commit&lt;/a&gt;. Looks like they changed some behavior, you can’t just go to that page anymore and log out. Bummer. But why?&lt;/p&gt;
&lt;h2 id=&quot;http-verbs-transfer-semantics-not-state&quot;&gt;HTTP verbs: transfer semantics, not state&lt;/h2&gt;
&lt;p&gt;As I’ve been doing my research for &lt;a href=&quot;http://designinghypermediaapis.com/&quot;&gt;my book on REST&lt;/a&gt;, I’ve been doing a lot of reading about HTTP. And I kept coming across these kinds of curious comments in the spec. For example, &lt;a href=&quot;http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6&quot;&gt;sec 9.6: PUT&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;HTTP/1.1 does not define how a PUT method affects the state of an origin server.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Uhhh… what? Don’t we all know that PUT means that we should be updating a resource? And that we have to send the whole representation?&lt;/p&gt;
&lt;p&gt;When trying to get to the bottom of this, I came across &lt;a href=&quot;http://www.imc.org/atom-protocol/mail-archive/msg05425.html&quot;&gt;this comment from Fielding&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;FWIW, PUT does not mean store. I must have repeated that a million times in webdav and related lists. HTTP defines the intended semantics of the communication – the expectations of each party. The protocol does not define how either side fulfills those expectations, and it makes damn sure it doesn’t prevent a server from having absolute authority over its own resources. Also, resources are known to change over time, so if a server accepts an invalid Atom entry via PUT one second and then immediately thereafter decides to change it to a valid entry for later GETs, life is grand.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Soooooooo wtf?&lt;/p&gt;
&lt;p&gt;Let’s take a look again at what &lt;code&gt;PUT&lt;/code&gt; does:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It says “store,” Roy says “I don’t mean store.” Uhhhh…&lt;/p&gt;
&lt;p&gt;Here’s my ‘translated for the laymen’ version of that quote:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;PUT means ‘I’d like to later GET something at this URI.’ If something is already there, update it. If there isn’t anything there, then create it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That’s it. It’s talking about the semantics of what goes on: create or update. It doesn’t actually say anything about how this is implemented. But if you PUT something to a URI, a GET needs to 200 afterwards. So what’s the difference between PUT and POST? &lt;a href=&quot;http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5&quot;&gt;HTTP sec 9.5: POST&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line.The actual function performed by the POST method is determined by the server and is usually dependent on the Request-URI. The posted entity is subordinate to that URI in the same way that a file is subordinate to a directory containing it, a news article is subordinate to a newsgroup to which it is posted, or a record is subordinate to a database.The action performed by the POST method might not result in a resource that can be identified by a URI.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Again, it’s really vague about what it &lt;em&gt;does&lt;/em&gt;. With POST, it basically says “You have no idea what a POST does.” What you &lt;em&gt;do&lt;/em&gt; know is the semantics of the action, POST ‘requests a new subordinate, but it might not create something.’&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;main&lt;/em&gt; difference is actually mentioned &lt;a href=&quot;http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.2&quot;&gt;here&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Methods can also have the property of “idempotence” in that (aside from error or expiration issues) the side-effects of N &gt; 0 identical requests is the same as for a single request. The methods GET, HEAD, PUT and DELETE share this property.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Semantics again. PUT is &lt;em&gt;idempotent&lt;/em&gt;, and POST is not. They could both be used for creation, they could both be used for updating. With POST, you don’t need a URI, and PUT specifies a specfic one. That’s it. Nowhere in those two sentences states ‘store in the database,’ nowhere does it says ‘full representation,’ nowhere does it say ‘POST is create and PUT is update.’ However you fulfill these semantics are up to you, but the semantics are what’s important.&lt;/p&gt;
&lt;h2 id=&quot;so-wtf-does-this-have-to-do-with-devise&quot;&gt;So wtf does this have to do with Devise?&lt;/h2&gt;
&lt;p&gt;The issue is that Devise’s old semantics were wrong. A GET to &lt;code&gt;/users/sign_out&lt;/code&gt; shouldn’t modify state: &lt;a href=&quot;http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1&quot;&gt;HTTP sec 9.1.1: Safe Methods&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered “safe”.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When Devise used GETs to log you out, that was a violation of the semantics of GET. Here’s the interesting part, though: Since POST is a super generic ‘unsafe action’ method, you could also use POST to represent a logging out. POST also has unsafe, non-idempotent semantics. DELETE specifically says delete, and POST says ‘any action,’ and ‘delete’ is a subset of ‘any action.’ So DELETE is &lt;em&gt;better&lt;/em&gt;, but POST is not &lt;em&gt;wrong&lt;/em&gt;, categorically.&lt;/p&gt;
&lt;h2 id=&quot;fixing-the-bug&quot;&gt;Fixing the ‘bug’&lt;/h2&gt;
&lt;p&gt;So how do we take care of this? Personally, I did the pragmatic thing. In &lt;code&gt;/config/initializers/devise.rb&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;config.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;sign_out_via&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; :delete&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;config.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;sign_out_via&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; :get&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Rails&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;test?&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, during normal operations, we have our usual DELETE semantics, but in our test environment, we can just hit it with GET. This way we don’t have to hit a page, use Javascript to make a link with DELETE, and hit the page. This keeps my test times down, means I can run my tests with rack-test and not Selenium, and still gives me a high level of confidence that my tests work properly, even though it’s technically not the exact same thing as production.&lt;/p&gt;
&lt;h2 id=&quot;in-conclusion&quot;&gt;In conclusion&lt;/h2&gt;
&lt;p&gt;The HTTP spec defines &lt;em&gt;semantics&lt;/em&gt; but not implementation details. Semantics should be obeyed. But in testing, obeying them 100% may not be worth it.&lt;/p&gt;</content:encoded></item><item><title>Rubinius is awesome</title><link>https://steveklabnik.com/writing/rubinius-is-awesome/</link><guid isPermaLink="true">https://steveklabnik.com/writing/rubinius-is-awesome/</guid><description>You walk into work tomorrow morning, and your boss says this: Boss: Hey, we’re gonna need to go ahead and have you implement require_relative in rubinius. We have some new servers coming in, and we’ll be running it in production, but we use some 1.9.2 features of MRI that haven’t…</description><pubDate>Tue, 04 Oct 2011 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;You walk into work tomorrow morning, and your boss says this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Boss: Hey, we’re gonna need to go ahead and have you implement require_relative in rubinius. We have some new servers coming in, and we’ll be running it in production, but we use some 1.9.2 features of MRI that haven’t been implemented yet. So if you could just go ahead and get to implementing that, that would be terrific, OK?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Wat do?&lt;/p&gt;
&lt;p&gt;(Disregard that your boss would never say this. I kinda wish some of mine would…)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You: Excuse me, I believe you have my stapler…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Err, sorry.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You: No problem, boss. Rubinius is mostly just Ruby, and it has a really helpful core team. I’m sure it won’t be a big deal.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Would you say this? Well, you should. I’m not gonna lie and say that &lt;em&gt;every&lt;/em&gt; feature is super simple to implement, or rbx-2.0 would be out already, but for a language interpreter, Rubinius is one of the easiest I’ve ever tried to get into. I actually did implement require_relative last night, and it took me about an hour and a half.&lt;/p&gt;
&lt;p&gt;This is my story.&lt;/p&gt;
&lt;p&gt;(note: dramatazation. Actual wording made unneccesarily silly to protect the innocent. please do try this at home)&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ ssh stevessecretserver&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ tmux attach&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;brings up irssi, I&apos;m already in #rubinius on Freenode&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#rubinius: steveklabnik: hey, I need require\_relative to run my app. How hard&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;would you think that is to implement?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#rubinius: evan: Naw, man, it&apos;d take like fifteen minutes. Go check out&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;http://rubygems.org/gems/rbx-require-relative, it&apos;s alredy basically got what&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;you want&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#rubinius: steveklabnik: sweet.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#rubinius: brixen: just grep for &apos;def require&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#rubinius: brixen: and run bin/mspec -tx19 core/kernel/require\_relative to&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;run the RubySpecs for it.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Armed with this knowledge, I found where require is defined in rbx:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(name)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  Rubinius&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;CodeLoader&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;module_function&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; :require&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course, I had to look at CodeLoader:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Searches for and loads Ruby source files and shared library extension&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# files. See CodeLoader.require for the rest of Kernel#require&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# functionality.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  Rubinius&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;synchronize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; false&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; unless&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; resolve_require_path&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; false&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; CodeLoader&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;loading?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; @load_path&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; @type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; :ruby&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      CodeLoader&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;loading&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; @load_path&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; @type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; :ruby&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    load_file&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    load_library&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; @type&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hmm, see &lt;code&gt;CodeLoader.require&lt;/code&gt;. There are codeloader18 and codeloader19 files…&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;module&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Rubinius&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; CodeLoader&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # Searches $LOAD_PATH for a file named +name+. Does not append any file&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # extension to +name+ while searching. Used by #load to resolve the name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # to a full path to load. Also used by #require when the file extension is&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # provided.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; search_load_path&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(name, loading)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      $LOAD_PATH.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;each&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; |dir|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;        path&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{dir}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{name}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; path &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; loadable? path&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; name &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; loading &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;and&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; loadable? &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;./&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{name}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Okay. So we define specific stuff into the 19 file. There’s also a kernel19. So I worked this up:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Attempt to load the given file, returning true if successful. Works just&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# like Kernel#require, except that it searches relative to the current&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# directory.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require_relative&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(name)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  Rubinius&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;CodeLoader&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;require_relative&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(name)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;module_function&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; :require_relative&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# requires files relative to the current directory. We do one interesting&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# check to make sure it&apos;s not called inside of an eval.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; self.require_relative&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(name)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  scope&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Rubinius&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;StaticScope&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;of_sender&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  script&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; scope.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;current_script&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; script&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    require&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; File&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;File&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;dirname&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(script.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;data_path&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), name)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    raise&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; LoadError&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Something is wrong in trying to get relative path&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But then… running the specs gives me bunches of errors. What gives?&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;back in irc&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#rubinius: steveklabnik: yo, my specs are failing, and I&apos;m a n00b. Halp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;pl0x?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#rubinius: brixen: oh, yeah, well, the StaticScope is the current scope,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;and you&apos;re down another method, so that&apos;s _totally_ gonna screw up&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;your paths. Just get it above and pass it down. Oh, and File.join is&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;dumb, File.expand_path that shit!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#rubinius: steveklabnik: words.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So then I made this one little change:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Attempt to load the given file, returning true if successful. Works just&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# like Kernel#require, except that it searches relative to the current&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# directory.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require_relative&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(name)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  scope&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Rubinius&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;StaticScope&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;of_sender&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  Rubinius&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;CodeLoader&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;require_relative&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(name, scope)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;module_function&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; :require_relative&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# requires files relative to the current directory. We do one interesting&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# check to make sure it&apos;s not called inside of an eval.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; self.require_relative&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(name, scope)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  script&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; scope.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;current_script&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; script&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    require&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; File&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;expand_path&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(name, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;File&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;dirname&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(script.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;data_path&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    raise&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; LoadError&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Something is wrong in trying to get relative path&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ bin/mspec -tx19 core/kernel/require_relativerubinius 2.0.0dev (1.9.2 cade3517 yyyy-mm-dd JI) [x86_64-apple-darwin10.8.0].....................Finished in 0.191995 seconds1 file, 20 examples, 47 expectations, 0 failures, 0 errors&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One more pull request, and I’ve got a patch in on rbx. I had one a few months ago, but this one was way cooler.&lt;/p&gt;
&lt;h2 id=&quot;in-conclusion&quot;&gt;In conclusion&lt;/h2&gt;
&lt;p&gt;Even if I didn’t have some code to look at, because Rubinius is just Ruby, it was really easy to dive in and check out the code, because it’s all Ruby. Seriously. Rubinius is just Ruby. Just Ruby. Ruby.&lt;/p&gt;
&lt;p&gt;So dive in and add some features today! If having an awesome alternate Ruby implementation isn’t enough for you, the rbx team will bribe you with special stickers for committers, and sweet black-on-black tshirts for people with 10 commits or more!&lt;/p&gt;</content:encoded></item><item><title>Real, modern Ruby development</title><link>https://steveklabnik.com/writing/real-modern-ruby-development/</link><guid isPermaLink="true">https://steveklabnik.com/writing/real-modern-ruby-development/</guid><description>I came across a blog post the other day titled Modern Ruby Development . While it’s a perfectly fine blog post (other than the digs at rvm…) it really should have been titled something more along the lines of “My default tooling to build a Rails application.” I thought of this…</description><pubDate>Wed, 28 Sep 2011 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I came across a blog post the other day titled &lt;a href=&quot;http://ascarter.net/2011/09/25/modern-ruby-development.html&quot;&gt;Modern Ruby Development&lt;/a&gt;. While it’s a perfectly fine blog post (other than the digs at rvm…) it really should have been titled something more along the lines of “My default tooling to build a Rails application.” I thought of this yesterday, as I was invited to show up at &lt;a href=&quot;http://www.vertigo.com/&quot;&gt;Vertigo&lt;/a&gt; and show them how we do things in the Open Source world. Vertigo builds lots of cool things, but they tend to be very .NET centric, and it was neat for both of us to see how the other half lives.&lt;/p&gt;
&lt;p&gt;Shortly before my ‘presentation,’ we decided that I’d basicaly just build a little web app in front of them. Live coding to the max! We decided for maximum awesome, and since I was in town for the Twilio conference, that I’d make a Twilio app that they could text and it’d text you ’hello world: you said #{msg}” back. I thought I’d share that process with you, too. I ended up throwing away the code, though, because I committed my account credentials into the git repo to simplify things, so I’ll just be describing it to you. Check my other posts for code stuff. ;)&lt;/p&gt;
&lt;p&gt;Oh, and one more thing: lots of this stuff is about getting ‘iteration zero’ out of the way: it’s setup work that you have to do to set the tone for everything else. In its own way, it’s also a tooling overview, I’ve just focused on the tools that help the process rather than the language stuff. I’ve already written a more ‘dev proccess’ style post over at &lt;a href=&quot;http://timelessrepo.com/bdd-with-rspec-and-steak&quot;&gt;Timeless&lt;/a&gt;, about BDD.&lt;/p&gt;
&lt;h2 id=&quot;rvm-rvmrc-create-192hello_text&quot;&gt;rvm –rvmrc –create 1.9.2@hello_text&lt;/h2&gt;
&lt;p&gt;First up: decide what Ruby you’re using. I talked breifly about MRI, Rubinius, and JRuby, and some pros and cons for each. I still tend to use MRI for my production code at the moment, but soon, rbx will become my default.&lt;/p&gt;
&lt;p&gt;I use rvm because it does exactly what I want.&lt;/p&gt;
&lt;h2 id=&quot;mvim-readmemd&quot;&gt;mvim README.md&lt;/h2&gt;
&lt;p&gt;I really enjoy &lt;a href=&quot;http://tom.preston-werner.com/2010/08/23/readme-driven-development.html&quot;&gt;README driven development&lt;/a&gt;. I didn’t actually demo this due to time constraints, but I generally write at least a minimal README.md before doing anything else. During Windy City Rails, Tom shared something that he likes doing: &lt;code&gt;mv README.md SPEC.md&lt;/code&gt;. That way, you can keep your actual README in sync with what the code does right now, but have the final one that you want to work towards too.&lt;/p&gt;
&lt;h2 id=&quot;git-push-origin&quot;&gt;git push origin&lt;/h2&gt;
&lt;p&gt;Now that we have a file, we can push it up to GitHub. A few clicks on the web, a &lt;code&gt;git add remote&lt;/code&gt; and &lt;code&gt;git push -u origin master&lt;/code&gt; and we’re off to the races.&lt;/p&gt;
&lt;h2 id=&quot;mvim-gemfile--bundle&quot;&gt;mvim Gemfile &amp;#x26;&amp;#x26; bundle&lt;/h2&gt;
&lt;p&gt;Next up we talked about Bundler, Gemfiles, and managing gems. I talked about the ability to run your own private gem server for internal gems, and how easy it is to build and publish a gem.&lt;/p&gt;
&lt;h2 id=&quot;mkdir-spec&quot;&gt;mkdir spec&lt;/h2&gt;
&lt;p&gt;I then generally type this. I would be lying to you if I told you that I do TDD 100% of the time. Sometimes, I get lazy. But I try to. And since testing is such a huge part of Ruby culture, and we have world-class testing tools, this is where I started.&lt;/p&gt;
&lt;p&gt;I wrote specs for a model class called SmsGateway. This class would handle sending a message to a phone via Twilio. I was able to show off rspec, talk about DSLs, mocking, and TDD.&lt;/p&gt;
&lt;h2 id=&quot;mvim-somethingrb&quot;&gt;mvim something.rb&lt;/h2&gt;
&lt;p&gt;In this case it’s sms_gateway.rb, but you know what I mean. Write some code, &lt;code&gt;rspec spec/sms_gateway_spec.rb&lt;/code&gt;, repeat. Red, Green, Refactor. Wheee!&lt;/p&gt;
&lt;h2 id=&quot;mvim-travisyml&quot;&gt;mvim .travis.yml&lt;/h2&gt;
&lt;p&gt;I wanted to show Travis off, so in my demo I did this before implementing the gateway class, but normally I’d do this after the first spec passes. Continuous Integration and even Continuous Deployment are awesome. Travis makes it super easy.&lt;/p&gt;
&lt;h2 id=&quot;sign-up-for-external-services&quot;&gt;Sign up for external services&lt;/h2&gt;
&lt;p&gt;I went over to Twilio’s site, registered a new account, and got my credentials. I used their docs to figure out where to put them, and how to get it all going inside my gateway class (I just mocked it out before), and talked about how needing to Google for docs is a weakness of Ruby.&lt;/p&gt;
&lt;h2 id=&quot;heroku-create--git-push-heroku-master&quot;&gt;heroku create &amp;#x26;&amp;#x26; git push heroku master&lt;/h2&gt;
&lt;p&gt;Then I showed them how to get going with Heroku, and how easy it was to start giving them hundreds of dollars per month when you need to scale. .NET people are used to paying for everything. ;)&lt;/p&gt;
&lt;p&gt;I also showed off one of my latest projects, which is an IRC bot that lets me deploy rstat.us into production. I have some serious Hubot envy. :D&lt;/p&gt;
&lt;h2 id=&quot;-repeat&quot;&gt;… repeat!&lt;/h2&gt;
&lt;p&gt;I’d be lying if I said it worked the first time, I accidentally made a loop where the app texted itself. Whoops! But that was cool, and showing off my debugging process (I’m a &lt;code&gt;puts/throw params&lt;/code&gt; debugger) was fun, as well. After realizing what I did wrong, we had the app working.&lt;/p&gt;
&lt;h2 id=&quot;its-not-quite-perfect&quot;&gt;It’s not quite perfect&lt;/h2&gt;
&lt;p&gt;This dev process isn’t perfect yet. Nothing ever is. I’m always trying to improve upon it, but I’m pretty happy with how quickly I’m able to turn out new projects with a reasonable amount of quality. What’s your workflow? How does mine suck? &lt;a href=&quot;mailto:steve@steveklabnik.com&quot;&gt;Email me&lt;/a&gt;, I’d love to hear about it.&lt;/p&gt;</content:encoded></item><item><title>Better Ruby Presenters</title><link>https://steveklabnik.com/writing/better-ruby-presenters/</link><guid isPermaLink="true">https://steveklabnik.com/writing/better-ruby-presenters/</guid><description>My last blog post caused a bit of a stir in some circles. I got a bunch of emails. Apparently, I need to expand on a few things. So here we go. Let’s rap about the Presenter pattern, shall we? No seriously, helpers suck In Ruby, everything is an object. Every bit of information…</description><pubDate>Fri, 09 Sep 2011 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;My &lt;a href=&quot;/writing/the-secret-to-rails-oo-design/&quot;&gt;last blog post&lt;/a&gt; caused a bit of a stir in some circles. I got a bunch of emails. Apparently, I need to expand on a few things. So here we go. Let’s rap about the Presenter pattern, shall we?&lt;/p&gt;
&lt;h2 id=&quot;no-seriously-helpers-suck&quot;&gt;No seriously, helpers suck&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;In Ruby, everything is an object. Every bit of information and code can be given their own properties and actions. - ruby-lang.org/about&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;… except helpers. Why is it in Ruby that everything is an object, even integers, yet as soon as we need to format a date, we all turn into Dijkstra and bust out structured programming? Actually, come to think of it, Dijkstra wouldn’t even write any code, because it’s beneath him, but you get the idea. (if you don’t get this, it’s a joke. About proofs, telescopes, and CS…) Helpers are like a compliment that you don’t want to give, but feel obligated to: “Yeah, I mean, well, you tried, and that’s what counts, right?”&lt;/p&gt;
&lt;p&gt;This is the topic of a future post, but when programming in a language, you want to work with its primary methods of abstraction. In Ruby, that’s objects, and there’s a good reason for that: functions don’t provide a sufficient amount of power to tackle hard problems. I don’t want to get into this either, but there’s a reason that objects exist, and that nobody’s making procedural languages anymore. No biggie. C has a special place in my heart.&lt;/p&gt;
&lt;p&gt;But I digress: objects &gt; functions. At least in the context of getting stuff done in Ruby. This pretty much applies to most of the rest of the points in this post, so just keep that in the back of your brain.&lt;/p&gt;
&lt;h2 id=&quot;why-not-a-class-method&quot;&gt;Why not a class method?&lt;/h2&gt;
&lt;p&gt;Well, first of all, &lt;a href=&quot;http://nicksda.apotomo.de/2011/07/are-class-methods-evil/&quot;&gt;class methods also suck&lt;/a&gt;. Here’s the issue: Can you tell me the difference between these two methods?&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &quot;hello&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Bar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; self.foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;hello&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bar&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;foo&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yep, that’s right. You can see it clearly from the last two lines: class methods are functions that happen to be namespaced. That means they’re slightly better, but really, &lt;code&gt;DictionaryPresenter.as_dictionary(something)&lt;/code&gt; might as well just be a helper. At least &lt;code&gt;as_dictionary(something)&lt;/code&gt; is shorter.&lt;/p&gt;
&lt;p&gt;Here’s another reason: I didn’t make that method be a class method, even though there was no state, because a really real presenter (I mean, that was a real world example, but…) generally works a little different. Usually, I make presenters that actually stand in for the objects they’re presenting. Check this out. Here’s the presenter I showed you:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; DictionaryPresenter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(collection)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @collection &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; collection&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; as_dictionary&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    dictionary&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;A&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Z&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;inject&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({}) {|h, l| h[l] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; []; h}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @collection.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;each&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; |p|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      dictionary[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    dictionary&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The real-world presenter that I used this for looked like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; DictionaryPresenter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  include&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Enumerable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(collection)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @dictionary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;A&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Z&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;inject&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({}) {|h, l| h[l] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; []; h}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    collection.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;each&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; |p|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      @dictionary[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; each&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;blk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @dictionary.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;each&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;blk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;… or close to this. There was an ‘other’ category, and a few other things… but you get the idea. Now, instead of this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;@posts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; DictionaryPresenter&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Post&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;all&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;as_dictionary&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You do this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;@posts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; DictionaryPresenter&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Post&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;all&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the presenter actually stands in for the hash. A subtle but important difference. This gives you more options, because you have a real, live object instead of just some random processing. With this simplistic presenter, you might not see a huge benefit, but often, you’ll want something a bit more complicated. And since this was what I had in my head, I didn’t make &lt;code&gt;as_dictionary&lt;/code&gt; be a static method.&lt;/p&gt;
&lt;p&gt;Oh, and presenters that decorate a single object rather than a collection often implement &lt;code&gt;method_missing&lt;/code&gt;, so that you only &lt;em&gt;add&lt;/em&gt; methods rather than hide most of them. Some don’t. It depends.&lt;/p&gt;
&lt;h2 id=&quot;blocks-vspolicy&quot;&gt;Blocks vs. Policy&lt;/h2&gt;
&lt;p&gt;I also showed off a Ruby version of a design pattern known as the Policy pattern, or sometimes the Strategy pattern. Turns out that Policy is often a bit heavyweight for Ruby, especially in an example like this, so I wanted to show you an alternate version of it, taking advantage of a Ruby feature: blocks.&lt;/p&gt;
&lt;p&gt;For reference, the old code, put into the new code:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; DictionaryPresenter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  include&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Enumerable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(policy, collection)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @dictionary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;A&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Z&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;inject&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({}) {|h, l| h[l] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; []; h}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    collection.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;each&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; |p|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      @dictionary[policy.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;category_for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; each&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;blk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @dictionary.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;each&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;blk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; UserCategorizationPolicy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; self.category_for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(user)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    user.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;username&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We could use blocks instead:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; DictionaryPresenter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  include&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Enumerable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(collection, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;blk)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @dictionary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;A&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Z&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;inject&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({}) {|h, l| h[l] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; []; h}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    collection.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;each&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; |p|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      @dictionary[blk.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;call&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; each&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;blk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @dictionary.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;each&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;blk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DictionaryPresenter&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Post&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;all&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; |item|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  item.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While this is shorter, and a bit more Rubyish, it also means that we lose the &lt;a href=&quot;http://en.wikipedia.org/wiki/Reification_(computer_science)&quot;&gt;reification&lt;/a&gt; of our concept of a policy. While this is &lt;em&gt;shorter&lt;/em&gt;, I find it more confusing. Why am I giving this one line block to the presenter? It’s not really clear to me. And I can’t give a better name to item… and if I want to change the policy, it has to be done in every place we use the presenter…&lt;/p&gt;
&lt;p&gt;This does get to the root of another thing that will end up being a follow-up: What’s the difference between closures and objects? If you don’t know, maybe this will get you thinking:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#ugh, this is slightly odd, thanks Ruby!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; apply&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(proc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;blk)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; block_given?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    blk.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;call&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    proc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;call&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;proc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Proc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  puts&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;a proc!&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; MyProc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; call&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    puts&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;an object!&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;my_proc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; MyProc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;apply &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  puts&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;a block!&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;apply &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;proc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;apply my_proc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Chew on that a while.&lt;/p&gt;
&lt;h2 id=&quot;this-is-too-verbose&quot;&gt;This is too verbose&lt;/h2&gt;
&lt;p&gt;Absolutely. &lt;code&gt;DictionaryPresenter.new(PostCategorizationPolicy, Post.all).as_dictionary&lt;/code&gt; is too long. 100% there. Good thing that I’d &lt;em&gt;actually&lt;/em&gt; write this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Dictionary&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Post&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;all&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;ByTitle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I switched the arguments around, because it reads better. When writing blog posts, you have to balance writing code samples that explain what you’re trying to say, and ones that are ‘real.’ I tend to be a bit more verbose with things like this, because it’s easier for someone who just jumps in to remember what all the parts are… then again, by &lt;em&gt;not&lt;/em&gt; showing the ‘real code,’ people might end up implementing the crappy, verbose version. It’s always a trade-off, and I may or may not make the right choice. It happens.&lt;/p&gt;
&lt;p&gt;And yes, even earlier in this blog post: I said &lt;code&gt;DictionaryPresenter&lt;/code&gt; and I’d really just say &lt;code&gt;Dictionary&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;where-does-all-of-this-go&quot;&gt;Where does all of this go?&lt;/h2&gt;
&lt;p&gt;You’ve got two options, and only one of them is good: You should make a directory in app for your presenters. In this case, I’d be running &lt;code&gt;touch app/presenters/dictionary.rb&lt;/code&gt; pretty quick. The other case is to put things in lib. This whole debacle uncovers something that @avdi went on a rant about over the last few days: models don’t have to inherit from anything. Here’s &lt;a href=&quot;http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller#Concepts&quot;&gt;what Wikipedia says about models&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The model manages the behaviour and data of the application domain, responds to requests for information about its state (usually from the view), and responds to instructions to change state (usually from the controller). In event-driven systems, the model notifies observers (usually views) when the information changes so that they can react.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;See anything about “saves stuff to the database?” Okay, ‘manages… data’ could be, but the point is, it’s not &lt;em&gt;required&lt;/em&gt;. Models are the reification of a concept that exists in your application domain. Persistance is not required for every concept.&lt;/p&gt;
&lt;p&gt;Therefore, if it relates to your problem domain, it goes in app. If it doesn’t, it goes in lib. Something like &lt;code&gt;Dictionary&lt;/code&gt;? Depends on how important you think it is. It’s probably pretty important; that’s why you made it a class.&lt;/p&gt;
&lt;h2 id=&quot;design-patterns-are-you-serious&quot;&gt;Design Patterns? Are you serious?&lt;/h2&gt;
&lt;p&gt;Yes. Design patterns don’t suck, Design patterns &lt;em&gt;in Java&lt;/em&gt; suck. I’m not even going to start this one here, expect more in this space soon.&lt;/p&gt;
&lt;p&gt;Design patterns are great, and they’re totally useful in Ruby.&lt;/p&gt;
&lt;h2 id=&quot;in-conclusion-a-shout-out&quot;&gt;In conclusion: A shout-out&lt;/h2&gt;
&lt;p&gt;I hope you’ve enjoyed this small digression on Presenters. If you’re gonna use presenters in your application, I encourage you to write simple ones as simple Ruby classes, but if they get slightly more complicated, you need to check out &lt;a href=&quot;https://github.com/jcasimir/draper&quot;&gt;Draper&lt;/a&gt; by my buddy Jeff Casimir. It lets you do stuff like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ArticleDecorator&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ApplicationDecorator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  decorates &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:article&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; author_name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    model.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;author&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;first_name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot; &quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; model.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;author&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;last_name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;article&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; ArticleDecorator&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;find&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;article.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;author_name&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There’s a lot of features to it, so check it out on GitHub. Totally worthwhile.&lt;/p&gt;</content:encoded></item><item><title>The secret to Rails OO design</title><link>https://steveklabnik.com/writing/the-secret-to-rails-oo-design/</link><guid isPermaLink="true">https://steveklabnik.com/writing/the-secret-to-rails-oo-design/</guid><description>UPDATE: I also have a follow-up here . I often tell people that I learned Ruby via Rails. This is pretty much the worst way to do it, but I’d learned so many programming languages by then that it didn’t hinder me too much. The one thing that it did do, however, was give me a…</description><pubDate>Tue, 06 Sep 2011 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;UPDATE: I also have a follow-up &lt;a href=&quot;/writing/better-ruby-presenters/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I often tell people that I learned Ruby via Rails. This is pretty much the worst way to do it, but I’d learned so many programming languages by then that it didn’t hinder me too much. The one thing that it did do, however, was give me a slightly twisted sense of how to properly design the classes needed in a Rails app. Luckily, I obsessively read other people’s code, and I’ve noticed that there’s one big thing that is common in most of the code that’s written by people whose design chops I respect.&lt;/p&gt;
&lt;p&gt;This particular thing is also seemingly unique to those people. It’s not something that people who don’t write good code attempt, but do badly. It’s like a flag, or signal. Now, when I see someone employ this, I instantly think “they get it.” Maybe I’m giving it too much credit, but this advanced design technique offers a ton of interconnected benefits throughout your Rails app, is easy to imploy, and speeds up your tests by an order of magnitude or more. Unfortunately, to many beginning Rails devs, it’s non-obvious, but I want &lt;em&gt;you&lt;/em&gt; to write better code, and so I’m here to ‘break the secret,’ if you will, and share this awesome, powerful technique with you.&lt;/p&gt;
&lt;p&gt;It’s called the ‘Plain Old Ruby Domain Object.’&lt;/p&gt;
&lt;p&gt;Yep, that’s right. A Ruby class that inherets from nothing. It’s so simple that it hides in plain sight. Loved by those who’ve mastered Rails, Plain Old Ruby Objects, or “POROs” as some like to call them, are a hidden weapon against complexity. Here’s what I mean. Examine this ‘simple’ model:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Post&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ActiveRecord::Base&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; self.as_dictionary&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    dictionary&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;A&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Z&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;inject&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({}) {|h, l| h[l] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; []; h}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    Post&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;all&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;each&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; |p|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      dictionary[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    dictionary&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We want to display an index page of all our posts, and do it by first letter. So we build up a dictionary, and then put our posts in it. I’m assuming we’re not paginating this, so don’t get caught up in querying for all Posts. The important thing is the idea: we can now display our posts by title:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Post&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;as_dictionary&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; |letter, list|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  %&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; letter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  %&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ul&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; list.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;each&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; |post|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    %&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; link_to post&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sure. And in one way, this code isn’t &lt;em&gt;bad&lt;/em&gt;. It’s also not good: We’ve mixed a presentational concern into our model, which is supposed to represent buisness logic. So let’s fix that, via a Presenter:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; DictionaryPresenter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(collection)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @collection &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; collection&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; as_dictionary&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    dictionary&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;A&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Z&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;inject&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({}) {|h, l| h[l] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; []; h}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @collection.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;each&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; |p|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      dictionary[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    dictionary&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can use it via &lt;code&gt;DictionaryPresenter.new(Post.all).as_dictionary&lt;/code&gt;. This has tons of benefits: we’ve moved presentation logic out of the model. We’ve &lt;em&gt;already&lt;/em&gt; added a new feature: any collection can now be displayed as a dictionary. We can easily write isolated tests for this presenter, and they will be &lt;em&gt;fast&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This post isn’t about the Presenter pattern, though, as much as I love it. This sort of concept appears in other places, too, “this domain concept deserves its own class.” Before we move to a different example, let’s expand on this further: if we want to sort our Posts by title, this class will work, but if we want to display, say, a User, it won’t, because Users don’t have titles. Furthermore, we’ll end up with a lot of Posts under “A,” because the word “a” is pretty common at the beginning of Posts, so we really want to take the second word in that case. We can make two kinds of presenters, but now we lose that generality, and the concept of ‘display by dictionary’ has two representations in our system again. You guessed it: POROs to the rescue!&lt;/p&gt;
&lt;p&gt;Let’s change our presenter slightly, to also accept an organizational policy object:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; DictionaryPresenter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(policy, collection)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @policy &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; policy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @collection &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; collection&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; as_dictionary&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    dictionary&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;A&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Z&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;inject&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({}) {|h, l| h[l] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; []; h}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @collection.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;each&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; |p|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      dictionary[@policy.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;category_for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    dictionary&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we can inject a policy, and have them be different:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; UserCategorizationPolicy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; self.category_for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(user)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    user.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;username&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; PostCategorizationPolicy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; self.category_for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(post)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; post.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;starts_with?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;A &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      post.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;split&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;][&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      post.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Bam!&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DictionaryPresenter&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;PostCategorizationPolicy&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Post&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;all&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;as_dictionary&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yeah, so that’s getting a bit long. It happens. :) You can see that now each concept has one representation in our system. The presenter doesn’t care how things are organized, and the policies only dictate how things are organized. In fact, my names sorta suck, maybe it should be “UsernamePolicy” and “TitlePolicy”, actually. We don’t even care what class they are!&lt;/p&gt;
&lt;p&gt;It goes further than that in other directions, too. Combining the flexibility of Ruby with one of my favorite patterns from “Working Effectively with Legacy Code,” we can take complex computations and turn them into objects. Look at this code:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Quote&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ActiveRecord::Base&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  #&amp;#x3C;snip&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; pretty_turnaround&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; turnaround.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;nil?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; purchased_at&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      offset&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; purchased_at&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      days_from_today&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ((&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; purchased_at.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;to_time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 24&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;floor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      offset&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;now&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      days_from_today&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; turnaround &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; offset &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (turnaround &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 24&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(time.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;strftime&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;%a&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Sat&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      time&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 24&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    elsif&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(time.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;strftime&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;%a&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Sun&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      time&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 24&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{time.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;strftime&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;%A %d %B&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;)}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{days_from_today}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; business days from today)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yikes! This method prints a turnaround time, but as you can see, it’s a complex calculation. We’d be able to understand this much more easily of we used Extract Method a few times to break it up, but then we risk polluting our Quote class with more stuff that’s only relevant to pretty turnaround calculation. Also, please ignore that this is also presentation on the model; we just care that it’s a complex bit of code for this example.&lt;/p&gt;
&lt;p&gt;Okay, so here’s the first step of this refactoring, which Feathers calls “Break Out Method Object.” You can open your copy of “Working Effectively With Legacy Code” and turn to page 330 to read more. If you don’t have a copy, get one. Anyway, I digress. Here’s the plan of attack:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a new class for the computation&lt;/li&gt;
&lt;li&gt;Define a method on that class to do the new work.&lt;/li&gt;
&lt;li&gt;Copy the body of the old method over, and change variable references to instance variables.&lt;/li&gt;
&lt;li&gt;Give it an initialize method that takes arguments to set the instance variables used in step 3.&lt;/li&gt;
&lt;li&gt;Make the old method delegate to the new class and method.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I’ve changed this slightly for Ruby, since we can’t Lean On The Compiler, and a few of Feathers’ steps are about doing this. Anyway, let’s try this on that code. Step 1:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Quote&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ActiveRecord::Base&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; pretty_turnaround&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    #snip&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; TurnaroundCalculator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Two:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; TurnaroundCalculator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; calculate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Three:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; TurnaroundCalculator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; calculate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; @turnaround.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;nil?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; @purchased_at&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      offset&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; @purchased_at&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      days_from_today&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ((&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; purchased_at.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;to_time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 24&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;floor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      offset&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;now&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      days_from_today&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; @turnaround &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; offset &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (@turnaround &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 24&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(time.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;strftime&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;%a&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Sat&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      time&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 24&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    elsif&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(time.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;strftime&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;%a&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Sun&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      time&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 24&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{time.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;strftime&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;%A %d %B&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;)}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{days_from_today}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; business days from today)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I like to give it a generic name at first, and then give it a better one in step 5, after we see what it really does. often our code will inform us of a good name.&lt;/p&gt;
&lt;p&gt;Four:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; TurnaroundCalculator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(purchased_at, turnaround)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @purchased_at &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; purchased_at&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @turnaround &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; turnaround&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; calculate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    #snip&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Five:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Quote&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ActiveRecord::Base&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; pretty_turnaround&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    TurnaroundCalculator&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(purchased_at, turnaround).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;calculate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Done! We should be able to run our tests and see them pass. Even if ‘run our tests’ consists of manually checking it out…&lt;/p&gt;
&lt;p&gt;So what’s the advantage here? Well, we now can start the refactoring process, but we’re in our own little clean room. We can extract methods into our TurnaroundCalcuator class without polluting Quote, we can write speedy tests for just the Calculator, and we’ve split out the idea of calculation into one place, where it can easily be changed later. Here’s our class, a few refactorings later:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; TurnaroundCalculator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; calculate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; @turnaround.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;nil?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{arrival_date}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;#{days_from_today}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; business days from today)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  protected&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; arrival_date&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    real_turnaround_time.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;strftime&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;%A %d %B&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; real_turnaround_time&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    adjust_time_for_weekends&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(start_time &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; turnaround_in_seconds)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; adjust_time_for_weekends&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(time)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; saturday?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(time)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      time &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 24&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    elsif&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; sunday?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(time)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      time &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 24&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      time&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; saturday?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(time)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    time.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;strftime&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;%a&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Sat&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; sunday?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(time)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    time.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;strftime&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;%a&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Sun&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; turnaround_in_seconds&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @turnaround &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 24&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; start_time&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    @purchased_at &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;or&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;now&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; days_from_today&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; @purchased_at&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      ((&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; @purchased_at.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;to_time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 24&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;floor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      @turnaround &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wow. This code I wrote three years ago isn’t perfect, but it’s almost understandable now. And each of the bits makes sense. This is after two or three waves of refactoring, which maybe I’ll cover in a separate post, becuase this was more illustrative than I thought… anyway, you get the idea. This is what I mean when I say that I shoot for roughly five-line methods in Ruby; if your code is well-factored, you can often get there.&lt;/p&gt;
&lt;p&gt;This idea of extracting domain objects that are pure Ruby is even in Rails itself. Check out this route:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;root &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:to&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dashboard#index&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:constraints&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;LoggedInConstraint&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Huh? LoggedInConstraint?&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; LoggedInConstraint&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; self.matches?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(request)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    current_user&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Whoah. Yep. A domain object that describes our routing policy. Awesome. Also, validations, blatantly stolen from &lt;a href=&quot;http://omgbloglol.com/post/392895742/improved-validations-in-rails-3&quot;&gt;omgbloglol&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; SomeClass&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; ActiveRecord:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Base&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  validate &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:category_id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:proper_category&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ProperCategoryValidator&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ActiveModel::EachValidator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; validate_each&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(record, attribute, value)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    unless&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; record.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;user&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;category_ids&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;include?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(value)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      record.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;errors&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; attribute, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;has bad category.&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This isn’t a plain Ruby class, but you get the idea.&lt;/p&gt;
&lt;p&gt;Now, you might be thinking, “Steve: This isn’t just for Rails! You’ve lied!” Why yes, actually, you’ve caught me: this isn’t the secret to Rails OO, it’s more of a general OO design guideline. But there’s something special about Rails which seems to lure you into the trap of never breaking classes down. Maybe it’s that &lt;code&gt;lib/&lt;/code&gt; feels like such a junk drawer. Maybe it’s that the fifteen minute examples only ever include ActiveRecord models. Maybe it’s that more Rails apps than not are (WARNING: UNSUBSTANTIATED CLAIM ALERT) closed source than open, so we don’t have as many good examples to draw upon. (I have this hunch since Rails is often used to build sites for companies. Gems? Sure? My web app? Not so much. I have no stats to back this up, though.)&lt;/p&gt;
&lt;p&gt;In summary: Extracting domain objects is good. They keep your tests fast, your code small, and make it easier to change things later. I have some more to say about this, specifically the “keeps test fast” part, but I’m already pushing it for length here. Until next time!&lt;/p&gt;</content:encoded></item><item><title>I&apos;m making it dead simple to contribute to Ruby&apos;s documentation</title><link>https://steveklabnik.com/writing/im-making-it-dead-simple-to-contribute-to-ruby-s-documentation/</link><guid isPermaLink="true">https://steveklabnik.com/writing/im-making-it-dead-simple-to-contribute-to-ruby-s-documentation/</guid><description>Okay! So, if you’d read my previous article on this , you’d know how easy it is to contribute to Ruby’s Documentaiton. But Steve, I’m still kinda scared. Okay, so here we go: I’m making it even easier on you. Send me what you want changed, and how, and I’ll make a patch and…</description><pubDate>Mon, 22 Aug 2011 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Okay! So, if you’d read &lt;a href=&quot;/writing/contributing-to-ruby-s-documentation/&quot;&gt;my previous article on this&lt;/a&gt;, you’d know how easy it is to contribute to Ruby’s Documentaiton.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;But Steve, I’m still kinda scared.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Okay, so here we go: I’m making it even easier on you.&lt;/p&gt;
&lt;p&gt;Send me what you want changed, and how, and I’ll make a patch and submit it on your behalf.&lt;/p&gt;
&lt;p&gt;No, seriously, I will. I already did once. &lt;a href=&quot;http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/38873&quot;&gt;This guy&lt;/a&gt; posted something about how it was too hard, &lt;a href=&quot;http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/38875&quot;&gt;so I made a patch for him&lt;/a&gt;. And now Ruby is better because of it.&lt;/p&gt;
&lt;h2 id=&quot;patches-dont-have-to-be-patches&quot;&gt;Patches don’t have to be patches&lt;/h2&gt;
&lt;p&gt;Seriously, I don’t even mean diff outputs. I just got this email:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; I&apos;m eager to contribute docs but I don&apos;t know where to start: I don&apos;t&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; mean pulling down the repo and all that, I mean, I see this link&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; here:http://segment7.net/projects/ruby/documentation\_coverage.txt but&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; all I see is a ton of &quot;# is documented&quot; comments. Where does a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; relative n00b begin? Poking around in the source code is, well,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; intimidating. I&apos;m completely new to this but I take direction well.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; Just point me in the right direction. Just give me something to&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; document, please!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I sent this back:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; No code diving needed! That&apos;s part of it. Let&apos;s do this: Find the documentation for one of your favorite methods. Here, I&apos;ll pick one: http://ruby-doc.org/core/classes/Array.html#M000278 okay, that looks okay, but look at compact!:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; &gt; Removes nil elements from the array. Returns nil if no changes were made, otherwise returns &amp;#x3C;/i&gt;ary&amp;#x3C;/i&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; Why&apos;s that &amp;#x3C;/i&gt; there? Total screw-up.  For example. So, send me this email:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; &quot;Hey Steve-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; Check out the docs for Array#compact!, here: http://ruby-doc.org/core/classes/Array.html#M000279 . There&apos;s an extra &amp;#x3C;/i&gt; that&apos;s screwing things up.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; -Jonathan&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; Done! I&apos;ll go from there. How about this one: &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; &quot;Hey Steve-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; I checked out the docs for Time._load, here: http://www.ruby-doc.org/core/classes/Time.html#M000394&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; These docs kind of suck. What if I don&apos;t know what Marshal is? There should at _least_ be a link to Marshall, here: http://ruby-doc.org/core/classes/Marshal.html And it should probably say something like &quot;You can get a dumped Time object by using _dump: http://www.ruby-doc.org/core/classes/Time.html#M000393 &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; - Jonathan&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; I&apos;m sure you can find something that&apos;s formatted wrong, or worded incorrectly, or anything else.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&gt; -Steve&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, the &lt;em&gt;closer&lt;/em&gt; it is to an actual patch, the faster I’ll be able to do it. A vague “this documentation is confusing, but I’m not sure why” is helpful, but will take longer. I’d rather get that email than not. If you’re not sure, hit send.&lt;/p&gt;
&lt;h2 id=&quot;just-do-it&quot;&gt;Just Do It&lt;/h2&gt;
&lt;p&gt;And so I’ll do it again. Scared to deal with doc patches? I’ll make them up. I’m serious. I’ll do it. Send them to me.&lt;/p&gt;
&lt;p&gt;That’s all.&lt;/p&gt;
&lt;p&gt;Send me patches. &lt;a href=&quot;mailto:steve@steveklabnik.com&quot;&gt;steve@steveklabnik.com&lt;/a&gt;. Do it.&lt;/p&gt;</content:encoded></item><item><title>Contributing to Ruby&apos;s documentation</title><link>https://steveklabnik.com/writing/contributing-to-ruby-s-documentation/</link><guid isPermaLink="true">https://steveklabnik.com/writing/contributing-to-ruby-s-documentation/</guid><description>Update! I’m now making it even easier than this: Read my new post about how I’ll do this for you . That said, if you want to do it yourself, the following will tell you how. Original Article Ruby 1.9.3 is coming out soon! drbrain has challenged the Ruby community to improve its…</description><pubDate>Tue, 10 May 2011 00:00:00 GMT</pubDate><content:encoded>&lt;h3 id=&quot;update&quot;&gt;Update!&lt;/h3&gt;
&lt;p&gt;I’m now making it even easier than this: &lt;a href=&quot;/writing/im-making-it-dead-simple-to-contribute-to-ruby-s-documentation/&quot;&gt;Read my new post about how I’ll do this for you&lt;/a&gt;. That said, if you want to do it yourself, the following will tell you how.&lt;/p&gt;
&lt;h3 id=&quot;original-article&quot;&gt;Original Article&lt;/h3&gt;
&lt;p&gt;Ruby 1.9.3 is coming out soon! &lt;a href=&quot;http://blog.segment7.net/2011/05/09/ruby-1-9-3-documentation-challenge&quot;&gt;drbrain has challenged the Ruby community to improve its documentation&lt;/a&gt;, but some people were asking about how to do so. So I made a video!&lt;/p&gt;
&lt;p&gt;Some small errata: drbrain has informed me that he should edit the Changelog, not me. So don’t do that. :)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://vimeo.com/23522731&quot;&gt;How to contribute to Ruby’s documentation.&lt;/a&gt; from &lt;a href=&quot;http://vimeo.com/steveklabnik&quot;&gt;Steve Klabnik&lt;/a&gt; on &lt;a href=&quot;http://vimeo.com/&quot;&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you don’t want to watch me talk about it, here’s the same info, in text:&lt;/p&gt;
&lt;p&gt;Getting the Ruby source is pretty easy. You can find it on GitHub, here: &lt;a href=&quot;http://github.com/ruby/ruby&quot;&gt;http://github.com/ruby/ruby&lt;/a&gt; . Click the “fork” button and clone down your own fork:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ git clone git@github.com:YOURUSERNAME/ruby.git&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After that’s done, type &lt;code&gt;cd ruby&lt;/code&gt; and add the main project as an upstream. This will let you keep up-to-date with the latest changes:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ git remote add upstream https://github.com/ruby/ruby.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ git fetch upstream&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Okay! Now that you’re all set up, poke around and find something that needs documented. I like to just look through the source, but you can also look &lt;a href=&quot;http://segment7.net/projects/ruby/documentation_coverage.txt&quot;&gt;here&lt;/a&gt; for a list of things that have no docs. Documentation is written in rdoc, and I’d check the recent commits that drbrain has been making to guide you in style. &lt;a href=&quot;https://github.com/ruby/ruby/commit/071a678a156dde974d8e470b659c89cb02b07b3b&quot;&gt;This commit&lt;/a&gt;, for example, is a pretty good template. You can also check out the formatting guides &lt;a href=&quot;http://rdoc.rubyforge.org/RDoc/Markup.html&quot;&gt;here&lt;/a&gt;. There’s also &lt;a href=&quot;http://rdoc.rubyforge.org/RDoc/Parser/Ruby.html&quot;&gt;this&lt;/a&gt; which explains some directives for .rb files and &lt;a href=&quot;http://rdoc.rubyforge.org/RDoc/Parser/C.html&quot;&gt;this&lt;/a&gt; which handles directives for .c files.&lt;/p&gt;
&lt;p&gt;Now that you’ve made a change to the documentation, you can regenerate the docs by using rdoc. First, grab the latest version from rubygems:&lt;/p&gt;
&lt;p&gt;$ gem install rdoc&lt;/p&gt;
&lt;p&gt;Always best to have the latest tools. Now do this to generate the docs:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ rdoc --o tmpdoc lib/rss*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I’m passing it in an output directory with op, since the doc directory is not an rdoc directory. rdoc will complain and refuse to overwrite those files, which is a good thing. I’m also passing in a pattern of what to compile documentation for, compiling all of it takes a few minutes! In this case, I chose to document the rss library.&lt;/p&gt;
&lt;p&gt;Now you have a website in rdocout. Open up its index.html, and poke around for what you’ve changed. If it all looks good, you’re ready to make a patch!&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ rm -r tmpdoc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ git add .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ git commit -m &quot;adding documentation for $SOMETHING&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, you have two options here. One is to simply push the change up to GitHub, and make a pull request.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ git push origin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;… aaand pull request. The core Ruby development doesn’t really happen on GitHub though, and so your patch may take a while to get included. If you really want to do it right, submit a patch to RedMine. We’ll use git to make this patch:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ git format-patch HEAD~1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This says “make a patch out of the last commit.” It’ll tell you a file name, it should start with 000.&lt;/p&gt;
&lt;p&gt;Now, sign up for the Ruby RedMine &lt;a href=&quot;http://bugs.ruby-lang.org/account/register&quot;&gt;here&lt;/a&gt;. Once you’ve clicked the confirmation email, &lt;a href=&quot;http://bugs.ruby-lang.org/projects/ruby-trunk/issues/new&quot;&gt;open a new ticket&lt;/a&gt;, and assign it to Eric Hodel, category DOC, and give it your Ruby version, even though it’s not a big deal here. Click ‘choose file’ and pick your patch, then ‘create and continue’ and BAM! You’re done!&lt;/p&gt;
&lt;p&gt;Let’s all pitch in and make this the best documented Ruby release ever! In writing documentation, you might even find some things that you’d like to help improve. ;)&lt;/p&gt;</content:encoded></item><item><title>Did you hear? I&apos;m Ruby Mendicant University&apos;s first visiting teacher</title><link>https://steveklabnik.com/writing/did-you-hear-i-m-ruby-mendicant-university-s-first-visiting-teacher/</link><guid isPermaLink="true">https://steveklabnik.com/writing/did-you-hear-i-m-ruby-mendicant-university-s-first-visiting-teacher/</guid><description>I’ve heard Ruby Mendicant University (also known as RMU, not to confuse you Robert Morris alums!) described as “the best kept secret of the Ruby community.” High praise, indeed. If you haven’t heard about RMU before, check out this presentation by Andrew Cox: TL;DR: RMU is a…</description><pubDate>Fri, 18 Mar 2011 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’ve heard &lt;a href=&quot;http://university.rubymendicant.com/&quot;&gt;Ruby Mendicant University&lt;/a&gt; (also known as RMU, not to confuse you Robert Morris alums!) described as “the best kept secret of the Ruby community.” High praise, indeed. If you haven’t heard about RMU before, check out this presentation by Andrew Cox:&lt;/p&gt;
&lt;p&gt;TL;DR: RMU is a free, online ‘unversity’ from Gregory Brown, author of ‘Ruby Best Practices.’ You enter an intermediate Rubyist, and you exit an expert.&lt;/p&gt;
&lt;p&gt;Anyway, RMU recently announced that &lt;a href=&quot;http://university.rubymendicant.com/changelog/visiting-teacher-2011-t2-steve-klabnik&quot;&gt;I’ll be their first visiting teacher&lt;/a&gt;. Basically, I’ll be hanging out, giving advice, and just generally being even more accessible to RMU students than I already am. Greg and I have talked a lot about education, Ruby, and a lot of other things… between Hackety’s ‘nothing to intermediate’ and RMU’s ‘intermediate to expert’ approaches to learning, anyone wanting to get up to speed with Ruby should have no shortage of resources at their disposal.&lt;/p&gt;
&lt;p&gt;If you’re feeling like you’ve got the hang of Ruby, but want to take it to the next level, &lt;a href=&quot;http://university.rubymendicant.com/admissions&quot;&gt;applications are open&lt;/a&gt;! Hopefully I’ll see you there.&lt;/p&gt;</content:encoded></item><item><title>Hackety Hack v1.0</title><link>https://steveklabnik.com/writing/hackety-hack-v1-0/</link><guid isPermaLink="true">https://steveklabnik.com/writing/hackety-hack-v1-0/</guid><description>It’s been a long journey. I have a lot to say about this, but it’ll have to wait until I’m not in the middle of nowhere spending some time with Maria’s family. I just wanted to tell you all Merry Christmas, and point you at the Hackety Hack v1.0 release announcement and the new…</description><pubDate>Sat, 25 Dec 2010 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;It’s been a long journey. I have a lot to say about this, but it’ll have to wait until I’m not in the middle of nowhere spending some time with Maria’s family. I just wanted to tell you all Merry Christmas, and point you at the &lt;a href=&quot;http://blog.hackety-hack.com/post/2457961910/merry-christmas-and-a-1-0-announcement&quot;&gt;Hackety Hack v1.0 release announcement&lt;/a&gt; and the new &lt;a href=&quot;http://hackety-hack.com/&quot;&gt;Hackety Hack website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Merry Christmas!&lt;/p&gt;</content:encoded></item><item><title>A word about _why, Whyday, and Hackety Hack</title><link>https://steveklabnik.com/writing/a-word-about-why-whyday-and-hackety-hack/</link><guid isPermaLink="true">https://steveklabnik.com/writing/a-word-about-why-whyday-and-hackety-hack/</guid><description>Today is Whyday. A programmer’s holiday. Today is the day that we don’t forget that programming isn’t all Agile and driven by behavior and Serious Business. Inside each cubicle, the hacker spirit is trying to burst free. Today, it will. Today, I’m also releasing a prerelease…</description><pubDate>Thu, 19 Aug 2010 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Today is Whyday. A programmer’s holiday. Today is the day that we don’t forget that programming isn’t all Agile and driven by behavior and Serious Business. Inside each cubicle, the hacker spirit is trying to burst free. Today, it will.&lt;/p&gt;
&lt;p&gt;Today, I’m also releasing a prerelease version of Hackety Hack 1.0. It’s been a long time coming. The announcement of Whyday got me thinking about the past year of a world without _why, and the ‘your domain is about to expire’ notices got me thinking about how I’ve now been the head of the Hackety Hack project for almost 12 months, too. I don’t like thinking about this, because I almost let _why down.&lt;/p&gt;
&lt;p&gt;I never met _why. I can’t really claim to know him, or know what his intentions were, but I think about him a lot. ‘_why’ the persona, really embodies everything that I love about software. The world owes _why a great debt, and I’d like to think that I’m doing what I can to repay him.&lt;/p&gt;
&lt;p&gt;At least, I am now. I don’t like to think about roughly 6 or 8 months of the last year of Hackety Hack; I did an exceptionally poor job of being a steward. Being alone, having no help, and having a bit of an identity crisis is an excuse; you can decide if it’s a good or poor one. But things have been looking up, and we’ve got some momentum, I owe a great debt to Fela for helping make this summer happen.&lt;/p&gt;
&lt;p&gt;I really do feel that the Little Coder still has a predicament, and I’m almost to the point where they can find some solace. I still feel that Hackety Hack could become an absolutely invauable project, I’ve just got to keep going. I can, I will, and I am. But I wouldn’t be able to if so many people didn’t care, say a nice world, or lend a hand.&lt;/p&gt;
&lt;p&gt;So thanks. And as ashbb would say, “Let’s all have fun with Hackety Hack!”&lt;/p&gt;
&lt;p&gt;Happy Whyday.&lt;/p&gt;
&lt;p&gt;EDIT: The release is now out. See the announcement &lt;a href=&quot;http://hackety-hack.com/posts/happy_whyday&quot;&gt;here&lt;/a&gt;, and get it &lt;a href=&quot;http://hackety-hack.com/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Thanks!&lt;/p&gt;</content:encoded></item><item><title>Writing a su feature with Authlogic</title><link>https://steveklabnik.com/writing/writing-a-su-feature-with-authlogic/</link><guid isPermaLink="true">https://steveklabnik.com/writing/writing-a-su-feature-with-authlogic/</guid><description>Sometimes, when responding to a support request, it’s nice to see what your users see. At the same time, you don’t want to ask your users for their passwords, out of respect for their privacy. So what do you do? Well, *NIX systems have a program called su. Here’s what man su has…</description><pubDate>Fri, 05 Mar 2010 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Sometimes, when responding to a support request, it’s nice to see what your users see. At the same time, you don’t want to ask your users for their passwords, out of respect for their privacy. So what do you do?&lt;/p&gt;
&lt;p&gt;Well, *NIX systems have a program called su. Here’s what man su has to say:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;NAME&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       su - run a shell with substitute user and group IDs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;SYNOPSIS&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       su [OPTION]... [-] [USER [ARG]...]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;DESCRIPTION&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       Change the effective user id and group id to that of USER.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;su can be thought of as “substitute user” or “switch user.” It’s a command system administrators use to assume the identity of one of their users, or a way for someone with the root password on the system to switch to the root account itself. So how can we incorporate this into a web application?&lt;/p&gt;
&lt;p&gt;Well, we want to first log ourselves out, and then log in as the user we’re su-ing to. That’s it. The tricky part, however, comes in when we’re logging in: as we said before, we don’t want to ask for their password. Luckily, Authlogic provides a way to create our UserSession object directly from a User object by just passing it to create.&lt;/p&gt;
&lt;p&gt;This lets us write a controller method to do this pretty easily:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; su&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  @user &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; User&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;find&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; params[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  current_user_session.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;destroy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  UserSession&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;create!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(@user)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  flash[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:notice&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;You&apos;ve been su-d to that user.&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  redirect_to dashboard_path&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add in a route:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;map.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;admin_su&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;/admin/su/:id&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:controller&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;admin&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:action&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; =&gt; &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;su&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And to a view somewhere in your administrative tools:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;%=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; link_to &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;log in as this user&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;admin_su_path&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(@user) &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;%&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we’re good to go!&lt;/p&gt;
&lt;p&gt;One last thing about this, though: You don’t want to let anyone who’s not an administrator do this, for obvious reasons. My administrative controllers always include a block like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;access_control &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  allow &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;:admin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;acl9 makes this really easy, but it’s really important.&lt;/p&gt;
&lt;p&gt;So there you have it. Easy as pie.&lt;/p&gt;
&lt;p&gt;EDIT: This post made the Rails subreddit, and &lt;a href=&quot;http://www.reddit.com/r/rails/comments/cb0da/writing_a_su_feature_with_authlogic/c0rf26w&quot;&gt;brettbender posted his code&lt;/a&gt; to get you back to admin.&lt;/p&gt;</content:encoded></item><item><title>The Hackety Manifesto</title><link>https://steveklabnik.com/writing/the-hackety-mainfesto/</link><guid isPermaLink="true">https://steveklabnik.com/writing/the-hackety-mainfesto/</guid><description>For those of you that don’t know, I’ve taken over a project by someone named _why. He dropped off of the face of the Internet back in March, and the community has picked up his works. Because I’ll be writing about the project in the future, and because I feel these words are…</description><pubDate>Thu, 31 Dec 2009 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;For those of you that don’t know, I’ve taken over a project by someone named _why. He dropped off of the face of the Internet back in March, and the community has picked up his works. Because I’ll be writing about the project in the future, and because I feel these words are still relevant, I’m reprinting the two of his essays that led up to the creation of the project, Hackety Hack, here on my blog. Here’s the second one.&lt;/p&gt;
&lt;p&gt;Enjoy.&lt;/p&gt;
&lt;h1 id=&quot;the-hackety-manifesto&quot;&gt;The Hackety Manifesto&lt;/h1&gt;
&lt;p&gt;Nearly four years ago, I wrote an essay called The Little Coder’s Predicament. It’s not too unusual. Lots of others like it have been written. The point is: programming just isn’t available to people like it was with the Commodore 64. I also outlined my requirements for a new cross-platform programming environment for beginners.&lt;/p&gt;
&lt;p&gt;The essay was widely linked on Slashdot, Reddit, Lambda, etc. I got lots of mail from people who both agreed and disagreed. Great. Nice. Good people all of them! And yet, nothing has changed. Not really!&lt;/p&gt;
&lt;p&gt;I’ve been told of the Xbox development kit and possible programming of Wii channels. The Playstation actually had a language. But none if it has met my criteria for a proper coding platform.&lt;/p&gt;
&lt;h2 id=&quot;an-aside-we-care-but-not-enough&quot;&gt;An Aside: We Care, But Not Enough&lt;/h2&gt;
&lt;p&gt;So, why has nothing been done about this? Maybe our interpreters and IDEs (ewww…) are good enough? Lots of people wrote in to say that HTML and JavaScript are the new BASIC. NO!!! You can’t be serious!!! So people have to write two languages now, which are intertwined in an almost inexplicable and unfathomable way? This doesn’t do it.&lt;/p&gt;
&lt;p&gt;Hello world should be one line.&lt;/p&gt;
&lt;p&gt;In fact, downloading an MP3 should be one line!!&lt;/p&gt;
&lt;p&gt;We just don’t care right now, do we? Programmers have a paid gig. So business is happily slurping them up. Look at our books. Look at the programming sites. Programming is tightly coupled to business. Often the first example is an e-commerce site! Our books are like FIFTY DOLLARS!! For crying out loud.&lt;/p&gt;
&lt;p&gt;This diatribe isn’t about business being bad. Of course you need to feed your family and drive an Audi.&lt;/p&gt;
&lt;p&gt;This diatribe is about adding some balance to the world of programming. Okay, so, let’s take things into our own hands and bring hacking to the young folks.&lt;/p&gt;
&lt;h2 id=&quot;the-bylaws-of-hackety&quot;&gt;The Bylaws of Hackety&lt;/h2&gt;
&lt;p&gt;Here are the rules by which Hackety Hack was established:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Beginners should be greeted to Hackety Hack by a cartoon character. (For the sake of argument, let’s call this character: Hacky Mouse.)&lt;/li&gt;
&lt;li&gt;Also, helpful sentences. Preferably short and with a period.&lt;/li&gt;
&lt;li&gt;Hackety Hack is fundamentally a browser and a programming language. For now, Gecko and Ruby.&lt;/li&gt;
&lt;li&gt;I’m only using Ruby because I know it. Hopefully, more languages can be added!&lt;/li&gt;
&lt;li&gt;Again, this isn’t about Ruby, it’s about simply offering a place for plainspeople to tinker with code.&lt;/li&gt;
&lt;li&gt;IDEs are a disaster. Newbs should see only one non-scary window free of tree controls and pinned windows and toolbars.&lt;/li&gt;
&lt;li&gt;As such, we want to stay away from project files and makefiles, the trappings of an IDE.&lt;/li&gt;
&lt;li&gt;Hackety Hack also adds simple libraries for common things.&lt;/li&gt;
&lt;li&gt;Common things are one-liners.&lt;/li&gt;
&lt;li&gt;Keep args and options to a minimum.&lt;/li&gt;
&lt;li&gt;In Ruby, blocks should be used to open up a method to more advanced possibilities.&lt;/li&gt;
&lt;li&gt;Help files are clean, short, simple. Lots of short examples. No frames.&lt;/li&gt;
&lt;li&gt;While all bug tickets are helpful and great, I just value tickets from beginners to a greater degree.&lt;/li&gt;
&lt;li&gt;Hackety Hack is free and will remain free henceforth.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Beyond that… anything which makes life easy and fun for Hackety Hackers is definitely encouraged, even demanded.&lt;/p&gt;</content:encoded></item></channel></rss>