<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://www.nethad.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.nethad.io/" rel="alternate" type="text/html" /><updated>2024-11-30T22:35:07+01:00</updated><id>https://www.nethad.io/feed.xml</id><title type="html">nethad.io</title><subtitle>Website by Thomas Ritter.
</subtitle><author><name>Thomas Ritter</name></author><entry><title type="html">How to Install Rails 7.0 on Windows (without WSL)</title><link href="https://www.nethad.io/2021/12/19/rails70-on-windows-without-wsl/" rel="alternate" type="text/html" title="How to Install Rails 7.0 on Windows (without WSL)" /><published>2021-12-19T00:00:00+01:00</published><updated>2021-12-19T00:00:00+01:00</updated><id>https://www.nethad.io/2021/12/19/rails70-on-windows-without-wsl</id><content type="html" xml:base="https://www.nethad.io/2021/12/19/rails70-on-windows-without-wsl/"><![CDATA[<h3 id="introduction">Introduction</h3>

<p>This guide is aimed at programming beginners who want to work with Ruby and Rails. If you’re a power user, skip to the end for the <a href="#tldr">TL;DR</a> section.</p>

<p>It assumes you’re on Windows 10 and have nothing pre-installed to work with Ruby and/or Rails, so this guide starts from scratch.</p>

<h3 id="preparation">Preparation</h3>

<p>Go to the start menu and open <code class="language-plaintext highlighter-rouge">Windows PowerShell</code>. It could also say <code class="language-plaintext highlighter-rouge">(x86)</code> at the end, but be sure <strong>not</strong> to select the <code class="language-plaintext highlighter-rouge">ISE</code> entry.</p>

<p><img src="/assets/images/winget-rails/startmenu-powershell.png" alt="Start menu with powershell" /></p>

<p>Now we check whether the <code class="language-plaintext highlighter-rouge">winget</code> package manager is already installed. For this, type <code class="language-plaintext highlighter-rouge">winget</code> into the PowerShell windows and hit Enter:</p>

<p><img src="/assets/images/winget-rails/winget-powershell-failed.png" alt="PowerShell showing that winget command is not installed" /></p>

<p>This probably looks like the image above. It prints out red text that tells you that <code class="language-plaintext highlighter-rouge">winget</code> is not installed, so let’s install that first.</p>

<p>Type in:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>exit
</code></pre></div></div>

<p>and hit Enter to <strong>close the PowerShell window now</strong>. If it does not show red text, but instead information about winget, then winget is already installed. In that case you can skip the installation and go directly <a href="#installing-the-packages">installing packages</a>.</p>

<h3 id="install-winget">Install winget</h3>

<p>To install <code class="language-plaintext highlighter-rouge">winget</code>, we have to go to the pre-installed Microsoft Store.</p>

<p>There we need to install the <a href="https://www.microsoft.com/en-us/p/app-installer/9nblggh4nns1">App Installer</a> by Microsoft.</p>

<p><img src="/assets/images/winget-rails/microsoft-store-app-installer.png" alt="App Installer in the Microsoft Store" /></p>

<p>By clicking the link, you should see a website that allows you to install the App Installer directly in the Microsoft Store. If it is already installed, make sure that you install the latest update before you continue.</p>

<p><strong>Close the previous PowerShell window if it is still open</strong>.</p>

<h3 id="installing-the-packages">Installing the packages</h3>

<p>Since you closed the previous PowerShell window, open a new window via the start menu.</p>

<p>Now enter the <code class="language-plaintext highlighter-rouge">winget</code> command and hit Enter. You should see the following output:</p>

<p><img src="/assets/images/winget-rails/winget-powershell-success.png" alt="PowerShell showing winget default help output" /></p>

<p>This means winget was installed successfully. We’re now going to install the first bunch of packages, namely NodeJS, Yarn, Git, Ruby.</p>

<p>Copy and paste the following into PowerShell and hit Enter:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>winget <span class="nb">install </span>OpenJS.NodeJS.LTS<span class="p">;</span> winget <span class="nb">install </span>Yarn.Yarn<span class="p">;</span> winget <span class="nb">install </span>Git.Git<span class="p">;</span> <span class="sb">`</span>
  winget <span class="nb">install </span>RubyInstallerTeam.RubyWithDevKit
</code></pre></div></div>

<p>You might get asked to accept the “msstore” source, which is the default Microsoft installation source. Type in “Y” and hit enter.</p>

<p>This will take a few minutes to install the packages. Small installation windows will pop up during this process and you’ll be asked to allow the installation of these packages like with any other installation. At the end it should look like this:</p>

<p><img src="/assets/images/winget-rails/installed-winget-packages.png" alt="PowerShell after packages installed with winget" /></p>

<p>Now type in <code class="language-plaintext highlighter-rouge">exit</code> (followed by Enter) to <strong>close the PowerShell window and re-open it again</strong>. Then enter the commands you see below:</p>

<p><img src="/assets/images/winget-rails/powershell-versions-check.png" alt="PowerShell with version checks" /></p>

<p>All four commands should print out a version similar to the one seen here.</p>

<h3 id="installing-ruby-development-tools">Installing Ruby development tools</h3>

<p>Now type in <code class="language-plaintext highlighter-rouge">exit</code> (followed by Enter) to <strong>close the PowerShell window</strong>, as we have done before.</p>

<p>Now go to the Start menu and choose the “Start Command Prompt with Ruby”:</p>

<p><img src="/assets/images/winget-rails/startmenu-command-prompt-ruby.png" alt="Start the Command prompt with Ruby" /></p>

<p>Enter this and hint enter:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ridk <span class="nb">install </span>3
</code></pre></div></div>

<p><img src="/assets/images/winget-rails/command-prompt-ruby-ridk.png" alt="Command prompt with Ruby showing the ridk command" /></p>

<p>This will take a while and will show a lot of colorful output. At the end it should look like this:</p>

<p><img src="/assets/images/winget-rails/command-promp-ruby-ridk-done.png" alt="Command prompt with Ruby after the ridk command is done" /></p>

<p>After the installation succeeded, we can type <code class="language-plaintext highlighter-rouge">exit</code> (followed by Enter) to close this window.</p>

<h3 id="installing-rails">Installing Rails</h3>

<p>In the file explorer, create a folder called “rails” in your home folder. You can also give it a different name, but we will use “rails” here.</p>

<p>Now <strong>open a PowerShell window again</strong>, then enter <code class="language-plaintext highlighter-rouge">cd </code> (the space afterwards is important!), drag the “rails” folder into the PowerShell window, drop it and then hit enter like this:</p>

<p><img src="/assets/images/winget-rails/cd-to-rails-folder.gif" alt="PowerShell: change to rails directory with drag and drop" /></p>

<p><code class="language-plaintext highlighter-rouge">cd</code> here stands for “change directory”, we told PowerShell to navigate to this directory.</p>

<p>Copy and paste this into PowerShell and hit Enter:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gem <span class="nb">install </span>sqlite3
</code></pre></div></div>

<p>This might take a minute, it will print out a few lines, at the end it should say “1 gem installed”.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gem <span class="nb">install </span>rails <span class="nt">--version</span> <span class="s2">"~&gt; 7.0"</span> <span class="nt">--no-doc</span>
</code></pre></div></div>

<article class="message is-info">
  <div class="message-body">
    Hint: at the time of writing this (December 2021), 7.0 was the lastest version. You might also want to just try `gem install rails --no-doc` and install the latest version.
  </div>
</article>

<p>This will produce a lot of output and install all of the rails dependencies. The second to last line should be “Successfully installed rails” including the Rails version number.</p>

<p>After that, enter:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rails new myapp
</code></pre></div></div>

<p>This also takes a few minutes, most probably longer than installing the packages. At the end, it should look like this:</p>

<p><img src="/assets/images/winget-rails/after-creating-myapp-70.png" alt="PowerShell after packages installed with winget" /></p>

<p>If you see this, Rails has been successfully installed. We also created a small Rails application called <code class="language-plaintext highlighter-rouge">myapp</code>.</p>

<h3 id="starting-the-rails-server">Starting the Rails server</h3>

<p>You can now change to this app and start the Rails server:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd </span>myapp
</code></pre></div></div>

<p>followed by:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bundle <span class="nb">exec </span>rails server
</code></pre></div></div>

<p>You should copy and paste both commands and hit Enter for both.</p>

<p>It should now look like this:</p>

<p><img src="/assets/images/winget-rails/rails-server-70.png" alt="PowerShell: starting rails server" /></p>

<p>This means the Rails server was started successfully. You can follow the instructions and open your Rails app in the browser by going to <a href="http://localhost:3000">http://localhost:3000</a>. You should see this:</p>

<p><img src="/assets/images/winget-rails/rails-70-success.png" alt="Fresh Rails web application in the browser" /></p>

<p>Congratulations! You successfully installed Rails and created your first app.</p>

<h3 id="bonus-level-installing-an-editor">Bonus level: installing an editor</h3>

<p>To comfortably work with your Rails project, I recommend to install an editor. A popular editor is VS Code. You can install it via PowerShell:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>winget <span class="nb">install </span>Microsoft.VisualStudioCode
</code></pre></div></div>

<p>After this, close and re-open the PowerShell window, navigate again to your <code class="language-plaintext highlighter-rouge">rails</code> folder, then to your <code class="language-plaintext highlighter-rouge">myapp</code> folder like we did in “Starting the Rails server”, then enter:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>code <span class="nb">.</span>
</code></pre></div></div>

<p>Now VS Code starts and opens your <code class="language-plaintext highlighter-rouge">myapp</code> project. You’re now ready to work on your app.</p>

<h3 id="closing-words">Closing words</h3>

<p>I hope this guide was helpful to you. Reach out via <a href="https://twitter.com/nethad">Twitter</a> if you liked it and/or if you had any issues with it. Feel free to share it. Cheers!</p>

<h3 id="tldr">TL;DR</h3>

<p>For power users, the short summary:</p>

<ol>
  <li>Check whether <code class="language-plaintext highlighter-rouge">winget</code> is installed, if not install or update App Installer from the Microsoft Store from <a href="https://www.microsoft.com/en-us/p/app-installer/9nblggh4nns1">here</a></li>
  <li>Open PowerShell and enter: <code class="language-plaintext highlighter-rouge">winget install OpenJS.NodeJS.LTS; winget install Yarn.Yarn; winget install Git.Git; winget install RubyInstallerTeam.RubyWithDevKit</code></li>
  <li>Close Powershell, open “Start Command Prompt with Ruby”, enter: <code class="language-plaintext highlighter-rouge">ridk install 3</code></li>
  <li>Close prompt, open a PowerShell, enter: <code class="language-plaintext highlighter-rouge">gem install sqlite3; gem install rails --version "~&gt; 7.0" --no-doc; rails new myapp</code></li>
  <li>A new app called myapp has been created, start the Rails server: <code class="language-plaintext highlighter-rouge">cd myapp; bundle exec rails server</code></li>
  <li>Open your app: <a href="http://localhost:3000">http://localhost:3000</a></li>
</ol>]]></content><author><name>Thomas Ritter</name></author><category term="rails" /><category term="windows" /><category term="install" /><category term="winget" /><category term="msys2" /><category term="mingw" /><summary type="html"><![CDATA[Introduction]]></summary></entry><entry><title type="html">How to Install Rails 6.1 on Windows with Winget</title><link href="https://www.nethad.io/2021/08/01/rails61-on-windows-with-winget/" rel="alternate" type="text/html" title="How to Install Rails 6.1 on Windows with Winget" /><published>2021-08-01T00:00:00+02:00</published><updated>2021-08-01T00:00:00+02:00</updated><id>https://www.nethad.io/2021/08/01/rails61-on-windows-with-winget</id><content type="html" xml:base="https://www.nethad.io/2021/08/01/rails61-on-windows-with-winget/"><![CDATA[<h3 id="introduction">Introduction</h3>

<article class="message is-danger">
  <div class="message-body">
    This guide is a little out of date. Check out the <a href="/2021/12/19/rails70-on-windows-without-wsl">improved Rails 7.0 guide</a>.
  </div>
</article>

<p>This guide is aimed at programming beginners who want to work with Ruby and Rails. If you’re a power user, skip to the end for the <a href="#tldr">TL;DR</a> section.</p>

<p>It assumes you’re on Windows 10 and have nothing pre-installed to work with Ruby and/or Rails, so this guide starts from scratch.</p>

<h3 id="preparation">Preparation</h3>

<p>Go to the start menu and open <code class="language-plaintext highlighter-rouge">Windows PowerShell</code>. It could also say <code class="language-plaintext highlighter-rouge">(x86)</code> at the end, but be sure <strong>not</strong> to select the <code class="language-plaintext highlighter-rouge">ISE</code> entry.</p>

<p>Now we check whether the <code class="language-plaintext highlighter-rouge">winget</code> package manager is already installed. For this, type <code class="language-plaintext highlighter-rouge">winget</code> into the PowerShell windows and hit Enter:</p>

<p><img src="/assets/images/winget-rails/winget-powershell-failed.png" alt="PowerShell showing that winget command is not installed" /></p>

<p>This probably looks like the image above. It prints out red text that tells you that <code class="language-plaintext highlighter-rouge">winget</code> is not installed, so let’s install that first. You should <strong>close the PowerShell window now</strong>. If it does not show red text, but instead information about winget, then winget is already installed. In that case you can skip the installation and go directly <a href="#installing-the-packages">installing packages</a>.</p>

<h3 id="install-winget">Install winget</h3>

<p>Go to <a href="https://github.com/microsoft/winget-cli/releases/latest">https://github.com/microsoft/winget-cli/releases/latest</a> and download the file that ends in <code class="language-plaintext highlighter-rouge">.msixbundle</code>. Once it’s downloaded, double-click the file. It will ask you to “Update App Installer”, so you click the “Update” button. This should only take a few seconds and should show you a mostly white screen with the message: “For proper function of the app, try to launch a Windows app package”. This means you successfully installed the winget package manager and can close this window. <strong>Close the previous PowerShell window if it is still open</strong>.</p>

<p><img src="/assets/images/winget-rails/winget-installer-1.png" alt="winget installer, first screen" />
<img src="/assets/images/winget-rails/winget-installer-2.png" alt="winget installer, second screen" /></p>

<h3 id="installing-the-packages">Installing the packages</h3>

<p>Open the <code class="language-plaintext highlighter-rouge">Windows PowerShell</code> as an <strong>administrator</strong> and hit “Yes” on the following User Account Control window:</p>

<p><img src="/assets/images/winget-rails/powershell-open-as-administrator.gif" alt="Open PowerShell as administrator" /></p>

<p>Now enter the <code class="language-plaintext highlighter-rouge">winget</code> command and hit Enter. You should see the following output:</p>

<p><img src="/assets/images/winget-rails/winget-powershell-success.png" alt="PowerShell showing winget default help output" /></p>

<p>This means winget was installed successfully. We’re now going to install the first bunch of packages, namely NodeJS, Yarn, Git, Ruby.</p>

<p>Copy and paste the following into PowerShell and hit Enter:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>winget <span class="nb">install </span>node<span class="p">;</span> winget <span class="nb">install </span>yarn<span class="p">;</span> winget <span class="nb">install </span>git<span class="p">;</span> <span class="sb">`</span>
  winget <span class="nb">install </span>RubyInstallerTeam.RubyWithDevKit
</code></pre></div></div>

<p>This will take a few minutes to install the packages. Small installation windows will pop up during this process but you don’t have to do anything at this point. At the end it should look like this:</p>

<p><img src="/assets/images/winget-rails/installed-winget-packages.png" alt="PowerShell after packages installed with winget" /></p>

<h3 id="installing-ruby-development-tools-and-rails">Installing Ruby development tools and Rails</h3>

<p>Now we have to <strong>close the PowerShell window and re-open it again as an administrator</strong>, as we have done before.</p>

<p>Enter this and hint enter:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ridk <span class="nb">install </span>3
</code></pre></div></div>

<p>This takes a while, after it’s done we have to <strong>close the PowerShell window and re-open it again</strong>. This time you can open it by just clicking on the start menu entry, you <strong>don’t need to be an administrator</strong>.</p>

<p>Create a folder called “rails” in your home folder. You can also give it a different name, but we will use “rails” here. Then, go back to your PowerShell, enter “cd “ (the space afterwards is important!), drag the “rails” folder into the PowerShell window, drop it and then hit enter like this:</p>

<p><img src="/assets/images/winget-rails/cd-to-rails-folder.gif" alt="PowerShell: change to rails directory with drag and drop" /></p>

<p><code class="language-plaintext highlighter-rouge">cd</code> here stands for “change directory”, we told PowerShell to navigate to this directory.</p>

<p>Copy and paste this into PowerShell and hit Enter:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gem <span class="nb">install </span>rails <span class="nt">--version</span> <span class="s2">"~&gt; 6.1"</span> <span class="nt">--no-doc</span>
</code></pre></div></div>

<p>Hint: at the time of writing this (August 2021), 6.1 was the lastest version. You might also want to just try <code class="language-plaintext highlighter-rouge">gem install rails --no-doc</code> and install the latest version.</p>

<p>After that, enter:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rails new myapp
</code></pre></div></div>

<p>This also takes a few minutes, most probably longer than installing the packages. At the end, it should look like this:</p>

<p><img src="/assets/images/winget-rails/after-creating-myapp.png" alt="PowerShell after packages installed with winget" /></p>

<p>If you see this, Rails has been successfully installed. We also created a small Rails application called <code class="language-plaintext highlighter-rouge">myapp</code>.</p>

<h3 id="starting-the-rails-server">Starting the Rails server</h3>

<p>You can now change to this app and start the Rails server:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd </span>myapp
</code></pre></div></div>

<p>followed by:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bundle <span class="nb">exec </span>rails server
</code></pre></div></div>

<p>You should copy and paste both commands and hit Enter for both.</p>

<p>It should now look like this:</p>

<p><img src="/assets/images/winget-rails/rails-server.png" alt="PowerShell: starting rails server" /></p>

<p>This means the Rails server was started successfully. You can follow the instructions and open your Rails app in the browser by going to <a href="http://localhost:3000">http://localhost:3000</a>. You should see this:</p>

<p><img src="/assets/images/winget-rails/localhost3000.png" alt="Fresh Rails web application in the browser" /></p>

<p>Congratulations! You successfully installed Rails and created your first app.</p>

<h3 id="bonus-level-installing-an-editor">Bonus level: installing an editor</h3>

<p>To comfortably work with your Rails project, I recommend to install an editor. A popular editor is VS Code. You can install it via PowerShell:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>winget <span class="nb">install </span>vscode
</code></pre></div></div>

<p>After this, close and re-open the PowerShell window, navigate again to your <code class="language-plaintext highlighter-rouge">rails</code> folder, then to your <code class="language-plaintext highlighter-rouge">myapp</code> folder like we did in “Starting the Rails server”, then enter:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>code <span class="nb">.</span>
</code></pre></div></div>

<p>Now VS Code starts and opens your <code class="language-plaintext highlighter-rouge">myapp</code> project. You’re now ready to work on your app.</p>

<h3 id="closing-words">Closing words</h3>

<p>I hope this guide was helpful to you. Reach out via <a href="https://twitter.com/nethad">Twitter</a> if you liked it and/or if you had any issues with it. Feel free to share it. Cheers!</p>

<h3 id="tldr">TL;DR</h3>

<p>For power users, the short summary:</p>

<ol>
  <li>Check whether <code class="language-plaintext highlighter-rouge">winget</code> is installed, if not install the msixbundle from <a href="https://github.com/microsoft/winget-cli/releases/latest">here</a></li>
  <li>Open PowerShell as administrator and enter: <code class="language-plaintext highlighter-rouge">winget install node; winget install yarn; winget install git; winget install RubyInstallerTeam.RubyWithDevKit</code></li>
  <li>Close Powershell, re-open as administrator: enter: <code class="language-plaintext highlighter-rouge">ridk install 3</code></li>
  <li>Close PowerShell, re-open as normal user, enter: <code class="language-plaintext highlighter-rouge">gem install rails --version "~&gt; 6.1" --no-doc; rails new myapp</code></li>
  <li>A new app called myapp has been created, start the Rails server: <code class="language-plaintext highlighter-rouge">cd myapp; bundle exec rails server</code></li>
  <li>Open your app: <a href="http://localhost:3000">http://localhost:3000</a></li>
</ol>]]></content><author><name>Thomas Ritter</name></author><category term="rails" /><category term="windows" /><category term="install" /><category term="winget" /><category term="msys2" /><category term="mingw" /><summary type="html"><![CDATA[Introduction]]></summary></entry><entry><title type="html">How to Install Rails 6 on Windows</title><link href="https://www.nethad.io/2019/12/09/rails-on-windows/" rel="alternate" type="text/html" title="How to Install Rails 6 on Windows" /><published>2019-12-09T00:00:00+01:00</published><updated>2019-12-09T00:00:00+01:00</updated><id>https://www.nethad.io/2019/12/09/rails-on-windows</id><content type="html" xml:base="https://www.nethad.io/2019/12/09/rails-on-windows/"><![CDATA[<blockquote>
  <p><strong>⚠ UPDATE from 2021 ⚠</strong></p>

  <p>Installing Rails on Windows 10 got a lot easier. <a href="/2021/08/01/rails61-on-windows-with-winget/">Follow my updated guide here</a>.</p>
</blockquote>

<p>As a coach for <a href="http://railsgirls.com/">RailsGirls</a> I had to assist in installing Rails on Windows recently. There’s an <a href="http://guides.railsgirls.com/install#setup-for-windows">official guide</a>, but even though it looks easy, it turns out to be a bit cumbersome to fully set up Rails and my goal was to make the process <strong>as easy and as fast as possible</strong>, without relying on RailsInstaller.</p>

<p>So what’ the goal here?</p>

<ul>
  <li>Install Ruby with RubyInstaller, which is up to date (unlike RailsInstaller)</li>
  <li>Install Rails 6.0, which is the latest version at the time of this writing</li>
  <li>Do <strong>not</strong> rely on Windows Subsystem for Linux (WSL) and bash, but use native Windows tools and PowerShell</li>
</ul>

<p>So let’s start!</p>

<h4 id="step-0-open-the-windows-powershell">Step 0: Open the Windows PowerShell</h4>

<p>This is the place where we enter all the following commands and it looks like this:</p>

<p><img src="/assets/images/win-rails/windows-powershell.png" alt="A screenshot of Windows PowerShell" /></p>

<p>You can enter the command <code class="language-plaintext highlighter-rouge">wmic os get OSArchitecture</code> and hit Enter, as seen in the screenshot:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Users\YourName</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">wmic</span><span class="w"> </span><span class="nx">os</span><span class="w"> </span><span class="nx">get</span><span class="w"> </span><span class="nx">OSArchitecture</span><span class="w">
</span></code></pre></div></div>

<p>If this gives you <code class="language-plaintext highlighter-rouge">64-bit</code>, you should download The RubyInstaller that ends in <code class="language-plaintext highlighter-rouge">x64</code>. If it says <code class="language-plaintext highlighter-rouge">32-bit</code> (which is unlikely), you should download RubyInstaller that ends in <code class="language-plaintext highlighter-rouge">x86</code>. If unsure, use 64 bit (x64).</p>

<h4 id="step-1-download-rubyinstaller-nodejs-and-yarn">Step 1: Download RubyInstaller, NodeJS and Yarn</h4>

<p>Create a new folder in your home directory and call it “railsgirls”. You could also give it a different name, but we will use this folder name from now on.</p>

<p>Then, download <a href="https://rubyinstaller.org/">RubyInstaller</a>, <a href="https://nodejs.org">NodeJS</a> and <a href="https://yarnpkg.com/">Yarn</a> into the railsgirls folder. You could get these packages by hand and rename them to <code class="language-plaintext highlighter-rouge">rubyinstaller.exe</code>, <code class="language-plaintext highlighter-rouge">nodejs.msi</code> and <code class="language-plaintext highlighter-rouge">yarn.msi</code>.</p>

<p><strong>Optional:</strong> Instead of downloading the files by hand, you can run these commands (most probably only working in Windows 10):</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">wget</span><span class="w"> </span><span class="nx">https://github.com/oneclick/rubyinstaller2/releases/download/RubyInstaller-2.6.5-1/rubyinstaller-devkit-2.6.5-1-x64.exe</span><span class="w"> </span><span class="nt">-o</span><span class="w"> </span><span class="nx">rubyinstaller.exe</span><span class="w">
</span><span class="n">wget</span><span class="w"> </span><span class="nx">https://nodejs.org/dist/v12.13.0/node-v12.13.0-x64.msi</span><span class="w"> </span><span class="nt">-o</span><span class="w"> </span><span class="nx">nodejs.msi</span><span class="w">
</span><span class="n">wget</span><span class="w"> </span><span class="nx">https://yarnpkg.com/latest.msi</span><span class="w"> </span><span class="nt">-o</span><span class="w"> </span><span class="nx">yarn.msi</span><span class="w">
</span></code></pre></div></div>

<p>So now you have a railsgirls folder with these 3 files in them. Navigate to that folder in your PowerShell:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Users\YourName</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">cd</span><span class="w"> </span><span class="nx">C:\Users\YourName\railsgirls</span><span class="w">
</span></code></pre></div></div>

<p>To not have to type the full folder path, you can enter <code class="language-plaintext highlighter-rouge">cd</code> (don’t forget the space after cd!) and then drag and drop the folder from Explorer address bar as seen here:</p>

<p><img src="/assets/images/win-rails/cd-folder-powershell.gif" alt="A give that shows how to change to the railsgirls folder" /></p>

<h4 id="step-2-create-installer-script-files">Step 2: Create installer script files</h4>

<p>Now, go to the Explorer folder (“railsgirls”) and create a new text file with a <strong>right-click &gt; New &gt; Text Document</strong>.</p>

<p><img src="/assets/images/win-rails/win-new-text-document.png" alt="Creating a new text file from the context menu" /></p>

<p>Rename the file <code class="language-plaintext highlighter-rouge">install1.bat</code> and make sure that you remove the <code class="language-plaintext highlighter-rouge">.txt</code> file extension from the suggested name.</p>

<p>Click yes when the following warning appears:</p>

<p><img src="/assets/images/win-rails/bat-rename-warning.png" alt="Rename batch file warning" /></p>

<p>Right-click on this new <code class="language-plaintext highlighter-rouge">install1.bat</code> file and select <strong>Edit</strong>:</p>

<p><img src="/assets/images/win-rails/edit-bat-menu.png" alt="Edit batch file with right-click" /></p>

<p>You will now see and empty Notepad editor. Paste the following text into this window:</p>

<div class="language-bat highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">REM install1.bat</span>
@echo <span class="na">off</span>
<span class="kd">If</span> <span class="ow">not</span> <span class="ow">exist</span> <span class="kd">rubyinstaller</span><span class="err">.exe</span> <span class="o">(</span>
    <span class="nb">echo</span> ###########################################################################
    <span class="nb">echo</span> #
    <span class="nb">echo</span> # <span class="kd">Could</span> <span class="ow">not</span> <span class="nb">find</span> <span class="kd">rubyinstaller</span><span class="err">.exe</span> <span class="k">in</span> <span class="kd">this</span> <span class="kd">folder</span>
    <span class="nb">echo</span> # <span class="kd">Get</span> <span class="kd">the</span> <span class="kd">latest</span> <span class="kd">version</span> <span class="kd">of</span> <span class="kd">Ruby</span><span class="na">+Devkit </span><span class="kd">from</span> <span class="kd">https</span>://rubyinstaller.org/ <span class="kd">and</span>
    <span class="nb">echo</span> # <span class="nb">rename</span> <span class="kd">the</span> <span class="kd">file</span> <span class="kd">to</span> <span class="kd">rubyinstaller</span><span class="err">.exe</span> <span class="kd">and</span> <span class="kd">put</span> <span class="kd">it</span> <span class="kd">into</span> <span class="kd">this</span> <span class="kd">folder</span>.
    <span class="nb">echo</span>
    <span class="nb">echo</span> ###########################################################################
    <span class="k">exit</span>
<span class="o">)</span>
<span class="kd">If</span> <span class="ow">not</span> <span class="ow">exist</span> <span class="kd">nodejs</span>.msi <span class="o">(</span>
    <span class="nb">echo</span> ###########################################################################
    <span class="nb">echo</span> #
    <span class="nb">echo</span> # <span class="kd">Could</span> <span class="ow">not</span> <span class="nb">find</span> <span class="kd">nodejs</span>.msi <span class="k">in</span> <span class="kd">this</span> <span class="kd">folder</span>.
    <span class="nb">echo</span> # <span class="kd">Download</span> <span class="kd">NodeJS</span> <span class="kd">LTS</span> <span class="kd">from</span> <span class="kd">https</span>://nodejs.org/en/ <span class="kd">and</span>
    <span class="nb">echo</span> # <span class="nb">rename</span> <span class="kd">the</span> <span class="kd">file</span> <span class="kd">to</span> <span class="kd">nodejs</span>.msi <span class="kd">and</span> <span class="kd">put</span> <span class="kd">it</span> <span class="kd">into</span> <span class="kd">this</span> <span class="kd">folder</span>.
    <span class="nb">echo</span> #
    <span class="nb">echo</span> ###########################################################################
    <span class="k">exit</span>
<span class="o">)</span>
<span class="kd">If</span> <span class="ow">not</span> <span class="ow">exist</span> <span class="kd">yarn</span>.msi <span class="o">(</span>
    <span class="nb">echo</span> ###########################################################################
    <span class="nb">echo</span> #
    <span class="nb">echo</span> # <span class="kd">Could</span> <span class="ow">not</span> <span class="nb">find</span> <span class="kd">yarn</span>.msi <span class="k">in</span> <span class="kd">this</span> <span class="kd">folder</span>.
    <span class="nb">echo</span> # <span class="kd">Download</span> <span class="kd">Yarn</span> <span class="kd">stable</span> <span class="kd">from</span> <span class="kd">https</span>://yarnpkg.com/ <span class="kd">and</span>
    <span class="nb">echo</span> # <span class="nb">rename</span> <span class="kd">the</span> <span class="kd">file</span> <span class="kd">to</span> <span class="kd">yarn</span>.msi <span class="kd">and</span> <span class="kd">put</span> <span class="kd">it</span> <span class="kd">into</span> <span class="kd">this</span> <span class="kd">folder</span>.
    <span class="nb">echo</span> #
    <span class="nb">echo</span> ###########################################################################
    <span class="k">exit</span>
<span class="o">)</span>
<span class="nb">echo</span> <span class="kd">All</span> <span class="kd">files</span> <span class="kd">are</span> <span class="kd">present</span><span class="o">,</span> <span class="kd">continuing</span> <span class="kd">with</span> <span class="kd">installation</span>...
<span class="nb">echo</span> <span class="kd">Installing</span> <span class="kd">RubyInstaller</span>...
.\rubyinstaller.exe <span class="na">/silent </span><span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> <span class="kd">Installing</span> <span class="kd">NodeJS</span>...  <span class="o">&amp;&amp;</span> <span class="se">^
</span>.\nodejs.msi <span class="na">/passive </span><span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> <span class="kd">Installing</span> <span class="kd">Yarn</span>...  <span class="o">&amp;&amp;</span> <span class="se">^
</span>.\yarn.msi <span class="na">/passive </span><span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> . <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> . <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> . <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> ######################################### <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> # <span class="kd">NOW</span> <span class="kd">RUN</span> <span class="kd">INSTALL2</span>.BAT                  # <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> ######################################### <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">pause</span>
</code></pre></div></div>

<p>and now save this file. It should look like this:</p>

<p><img src="/assets/images/win-rails/edit-bat-notepad.png" alt="Notepad windows with pasted batch code" /></p>

<p>After you saved this file, you can close Notepad.</p>

<p><strong>Create a new file</strong> called <code class="language-plaintext highlighter-rouge">install2.bat</code> exactly the same way (rename, remove .txt extension), with the following content:</p>

<div class="language-bat highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">REM install2.bat</span>
@echo <span class="na">off</span>
<span class="nb">echo</span> <span class="kd">Installing</span> <span class="kd">MinGW</span>...  <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="kd">ridk</span> <span class="kd">install</span> <span class="m">3</span> <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> <span class="kd">Installing</span> <span class="kd">Bundler</span>...  <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="kd">gem</span> <span class="kd">install</span> <span class="kd">bundler</span> <span class="na">--no-document </span><span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> <span class="kd">Installing</span> <span class="kd">SQLite</span>...  <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="kd">gem</span> <span class="kd">install</span> <span class="kd">sqlite3</span> <span class="na">--platform</span><span class="o">=</span><span class="kd">ruby</span> <span class="na">--no-document </span><span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> <span class="kd">Installing</span> <span class="kd">Rails</span>...  <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="kd">gem</span> <span class="kd">install</span> <span class="kd">rails</span> <span class="na">--no-document </span><span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> <span class="kd">Installing</span> <span class="kd">Setting</span> <span class="kd">up</span> <span class="kd">new</span> <span class="kd">rails</span> <span class="kd">app</span>...  <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="kd">rails</span> <span class="kd">new</span> <span class="kd">myapp</span> <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> . <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> . <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> . <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> ######################################### <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> # <span class="kd">ALL</span> <span class="kd">DONE</span>.                             # <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">echo</span> ######################################### <span class="o">&amp;&amp;</span> <span class="se">^
</span><span class="nb">pause</span>
</code></pre></div></div>

<p>Also save this file and close Notepad.</p>

<p>Now back to your PowerShell. Type in <code class="language-plaintext highlighter-rouge">ls</code> and hit Enter:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Users\YourName\railsgirls</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">ls</span><span class="w">
</span></code></pre></div></div>

<p>You should see your two bat files and the three installers:</p>

<p><img src="/assets/images/win-rails/ls-before-install.png" alt="PowerShell: A list all files in the railsgirls folder" /></p>

<h4 id="step-3-run-the-installer-scripts">Step 3: Run the installer scripts</h4>

<p>In your PowerShell, first, run <code class="language-plaintext highlighter-rouge">.\install1.bat</code>:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Users\YourName\railsgirls</span><span class="err">&gt;</span><span class="w"> </span><span class="o">.</span><span class="nx">\install1.bat</span><span class="w">
</span></code></pre></div></div>

<p>This installs RubyInstaller, NodeJS and Yarn. You will see a few installer windows, they might prompt you for <strong>permission</strong>, other than that they should run by themselves.</p>

<p>At the end you will see:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#########################################</span><span class="w">
</span><span class="c"># NOW RUN INSTALL2.BAT                  #</span><span class="w">
</span><span class="c">#########################################</span><span class="w">
</span><span class="n">Press</span><span class="w"> </span><span class="nx">any</span><span class="w"> </span><span class="nx">key</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="nx">continue</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="o">.</span><span class="w">
</span></code></pre></div></div>

<p>Now, <strong>close this window and open a new PowerShell</strong>. Navigate to your railsgirls folder again (with <code class="language-plaintext highlighter-rouge">cd</code>, as above).</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Users\YourName</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">cd</span><span class="w"> </span><span class="nx">C:\Users\YourName\railsgirls</span><span class="w">
</span></code></pre></div></div>

<p>Now run the <code class="language-plaintext highlighter-rouge">.\install2.bat</code> script:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Users\YourName\railsgirls</span><span class="err">&gt;</span><span class="w"> </span><span class="o">.</span><span class="nx">\install2.bat</span><span class="w">
</span></code></pre></div></div>

<p>And the end you should see:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Webpacker</span><span class="w"> </span><span class="nx">successfully</span><span class="w"> </span><span class="nx">installed</span><span class="w"> </span><span class="err">🎉</span><span class="w"> </span><span class="err">🍰</span><span class="w">
</span><span class="o">.</span><span class="w">
</span><span class="o">.</span><span class="w">
</span><span class="o">.</span><span class="w">
</span><span class="c">#########################################</span><span class="w">
</span><span class="c"># ALL DONE.                             #</span><span class="w">
</span><span class="c">#########################################</span><span class="w">
</span><span class="n">Press</span><span class="w"> </span><span class="nx">any</span><span class="w"> </span><span class="nx">key</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="nx">continue</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="o">.</span><span class="w">
</span></code></pre></div></div>

<p>Nice! Now you installed Rails with all its dependencies, so you’re done. Congratulations!</p>

<h4 id="step-4-optional-run-your-rails-application">Step 4: OPTIONAL: Run your Rails application</h4>

<p>The <code class="language-plaintext highlighter-rouge">install2.bat</code> script created a new folder called <code class="language-plaintext highlighter-rouge">myapp</code> with a Rails application in your railsgirls folder.</p>

<p>After you hit enter to exit the installer script, you can navigate to that Rails app with:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Users\YourName\railsgirls</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">cd</span><span class="w"> </span><span class="nx">myapp</span><span class="w">
</span></code></pre></div></div>

<p>And inside that folder run:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Users\YourName\railsgirls\myapp</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">bundle</span><span class="w"> </span><span class="nx">exec</span><span class="w"> </span><span class="nx">rails</span><span class="w"> </span><span class="nx">server</span><span class="w">
</span></code></pre></div></div>

<p>This might take 10 to 15 seconds, and should look like this:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Users\YourName\railsgirls\myapp</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">bundle</span><span class="w"> </span><span class="nx">exec</span><span class="w"> </span><span class="nx">rails</span><span class="w"> </span><span class="nx">server</span><span class="w">
</span><span class="o">=</span><span class="err">&gt;</span><span class="w"> </span><span class="n">Booting</span><span class="w"> </span><span class="nx">Puma</span><span class="w">
</span><span class="o">=</span><span class="err">&gt;</span><span class="w"> </span><span class="n">Rails</span><span class="w"> </span><span class="nx">6.0.1</span><span class="w"> </span><span class="nx">application</span><span class="w"> </span><span class="nx">starting</span><span class="w"> </span><span class="nx">in</span><span class="w"> </span><span class="nx">development</span><span class="w">
</span><span class="o">=</span><span class="err">&gt;</span><span class="w"> </span><span class="n">Run</span><span class="w"> </span><span class="se">`r</span><span class="nx">ails</span><span class="w"> </span><span class="nx">server</span><span class="w"> </span><span class="nt">--help</span><span class="se">` </span><span class="nx">for</span><span class="w"> </span><span class="nx">more</span><span class="w"> </span><span class="nx">startup</span><span class="w"> </span><span class="nx">options</span><span class="w">
</span><span class="o">***</span><span class="w"> </span><span class="n">SIGUSR2</span><span class="w"> </span><span class="nx">not</span><span class="w"> </span><span class="nx">implemented</span><span class="p">,</span><span class="w"> </span><span class="nx">signal</span><span class="w"> </span><span class="nx">based</span><span class="w"> </span><span class="nx">restart</span><span class="w"> </span><span class="nx">unavailable</span><span class="o">!</span><span class="w">
</span><span class="o">***</span><span class="w"> </span><span class="n">SIGUSR1</span><span class="w"> </span><span class="nx">not</span><span class="w"> </span><span class="nx">implemented</span><span class="p">,</span><span class="w"> </span><span class="nx">signal</span><span class="w"> </span><span class="nx">based</span><span class="w"> </span><span class="nx">restart</span><span class="w"> </span><span class="nx">unavailable</span><span class="o">!</span><span class="w">
</span><span class="o">***</span><span class="w"> </span><span class="n">SIGHUP</span><span class="w"> </span><span class="nx">not</span><span class="w"> </span><span class="nx">implemented</span><span class="p">,</span><span class="w"> </span><span class="nx">signal</span><span class="w"> </span><span class="nx">based</span><span class="w"> </span><span class="nx">logs</span><span class="w"> </span><span class="nx">reopening</span><span class="w"> </span><span class="nx">unavailable</span><span class="o">!</span><span class="w">
</span><span class="n">Puma</span><span class="w"> </span><span class="nx">starting</span><span class="w"> </span><span class="nx">in</span><span class="w"> </span><span class="nx">single</span><span class="w"> </span><span class="nx">mode...</span><span class="w">
</span><span class="o">*</span><span class="w"> </span><span class="n">Version</span><span class="w"> </span><span class="nx">4.3.1</span><span class="w"> </span><span class="p">(</span><span class="n">ruby</span><span class="w"> </span><span class="nx">2.6.5-p114</span><span class="p">),</span><span class="w"> </span><span class="nx">codename:</span><span class="w"> </span><span class="nx">Mysterious</span><span class="w"> </span><span class="nx">Traveller</span><span class="w">
</span><span class="o">*</span><span class="w"> </span><span class="n">Min</span><span class="w"> </span><span class="nx">threads:</span><span class="w"> </span><span class="nx">5</span><span class="p">,</span><span class="w"> </span><span class="nx">max</span><span class="w"> </span><span class="nx">threads:</span><span class="w"> </span><span class="nx">5</span><span class="w">
</span><span class="o">*</span><span class="w"> </span><span class="n">Environment:</span><span class="w"> </span><span class="nx">development</span><span class="w">
</span><span class="o">*</span><span class="w"> </span><span class="n">Listening</span><span class="w"> </span><span class="nx">on</span><span class="w"> </span><span class="nx">tcp://</span><span class="p">[::</span><span class="mi">1</span><span class="p">]:</span><span class="nx">3000</span><span class="w">
</span><span class="o">*</span><span class="w"> </span><span class="n">Listening</span><span class="w"> </span><span class="nx">on</span><span class="w"> </span><span class="nx">tcp://127.0.0.1:3000</span><span class="w">
</span><span class="n">Use</span><span class="w"> </span><span class="nx">Ctrl-C</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="nx">stop</span><span class="w">
</span></code></pre></div></div>

<p>Go to your browser and enter: <code class="language-plaintext highlighter-rouge">http://localhost:3000</code></p>

<p>and you should see this:</p>

<p><img src="/assets/images/win-rails/rails-server-hello-world.png" alt="The Rails welcome page" /></p>

<p>And that’s it!</p>

<p>If you found this installation guide helpful, share it with others. If you have any feedback, get in touch with me on <a href="http://www.twitter.com/nethad">Twitter</a>.</p>

<p>Thanks!</p>]]></content><author><name>Thomas Ritter</name></author><category term="rails" /><category term="windows" /><category term="install" /><category term="msys2" /><category term="mingw" /><summary type="html"><![CDATA[⚠ UPDATE from 2021 ⚠ Installing Rails on Windows 10 got a lot easier. Follow my updated guide here.]]></summary></entry><entry><title type="html">How we sped up our model spec to run 12 times faster</title><link href="https://www.nethad.io/2015/02/11/ability-spec-speedup/" rel="alternate" type="text/html" title="How we sped up our model spec to run 12 times faster" /><published>2015-02-11T00:00:00+01:00</published><updated>2015-02-11T00:00:00+01:00</updated><id>https://www.nethad.io/2015/02/11/ability-spec-speedup</id><content type="html" xml:base="https://www.nethad.io/2015/02/11/ability-spec-speedup/"><![CDATA[<p>We are using <a href="https://github.com/CanCanCommunity/cancancan">cancancan</a> as an authorization gem for one of our applications. To make sure that our authorization rules are correct, we unit-tested the <code class="language-plaintext highlighter-rouge">Ability</code> object. In the beginning, the test was quite fast, but the more rules we added, the longer it took to run the whole model test.</p>

<p>When we analyzed what was slowing down our test, we saw that quite some time is actually used persisting our models to the database with <a href="https://github.com/thoughtbot/factory_girl">factory_girl</a> as part of the test setup. It took a bit more than 60 seconds to run the whole ability spec, which is far too much for a model test.</p>

<p>Let’s look at an excerpt of our ability and its spec:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># ability.rb</span>

<span class="k">def</span> <span class="nf">acceptance_modes</span>
  <span class="n">can</span> <span class="p">[</span><span class="ss">:read</span><span class="p">],</span> <span class="no">AcceptanceMode</span>

  <span class="k">if</span> <span class="vi">@user</span><span class="p">.</span><span class="nf">admin?</span>
    <span class="n">can</span> <span class="p">[</span><span class="ss">:create</span><span class="p">,</span> <span class="ss">:update</span><span class="p">],</span> <span class="no">AcceptanceMode</span>
    <span class="n">can</span> <span class="ss">:destroy</span><span class="p">,</span> <span class="no">AcceptanceMode</span> <span class="k">do</span> <span class="o">|</span><span class="n">acceptance_mode</span><span class="o">|</span>
      <span class="n">acceptance_mode</span><span class="p">.</span><span class="nf">policies</span><span class="p">.</span><span class="nf">empty?</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># ability_spec.rb</span>

<span class="n">describe</span> <span class="no">Ability</span> <span class="k">do</span>

  <span class="n">let!</span><span class="p">(</span><span class="ss">:admin_user</span><span class="p">)</span> <span class="p">{</span> <span class="n">create</span><span class="p">(</span><span class="ss">:admin_user</span><span class="p">)</span> <span class="p">}</span>
  <span class="n">subject!</span><span class="p">(</span><span class="ss">:ability</span><span class="p">)</span> <span class="p">{</span> <span class="no">Ability</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">admin_user</span><span class="p">)</span> <span class="p">}</span>

  <span class="n">context</span> <span class="s1">'acceptance mode'</span> <span class="k">do</span>

      <span class="n">let!</span><span class="p">(</span><span class="ss">:acceptance_mode</span><span class="p">)</span> <span class="p">{</span> <span class="n">create</span><span class="p">(</span><span class="ss">:acceptance_mode</span><span class="p">)</span> <span class="p">}</span>

      <span class="n">before</span><span class="p">(</span><span class="ss">:each</span><span class="p">)</span> <span class="k">do</span>
        <span class="n">create</span><span class="p">(</span><span class="ss">:policy</span><span class="p">,</span> <span class="ss">:acceptance_mode</span> <span class="o">=&gt;</span> <span class="n">acceptance_mode</span><span class="p">)</span>
      <span class="k">end</span>

      <span class="p">[</span><span class="ss">:read</span><span class="p">,</span> <span class="ss">:create</span><span class="p">,</span> <span class="ss">:update</span><span class="p">].</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">action</span><span class="o">|</span>
        <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_able_to</span><span class="p">(</span><span class="n">action</span><span class="p">,</span> <span class="n">acceptance_mode</span><span class="p">)</span> <span class="p">}</span>
      <span class="k">end</span>

      <span class="n">it</span> <span class="p">{</span> <span class="n">should_not</span> <span class="n">be_able_to</span><span class="p">(</span><span class="ss">:destroy</span><span class="p">,</span> <span class="n">acceptance_mode</span><span class="p">)</span> <span class="p">}</span>

  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># ability_matcher.rb</span>

<span class="k">module</span> <span class="nn">AbilityHelper</span>
  <span class="kp">extend</span> <span class="no">RSpec</span><span class="o">::</span><span class="no">Matchers</span><span class="o">::</span><span class="no">DSL</span>

  <span class="n">matcher</span> <span class="ss">:be_able_to</span> <span class="k">do</span> <span class="o">|</span><span class="n">action</span><span class="p">,</span> <span class="n">object</span><span class="o">|</span>
    <span class="n">match</span> <span class="k">do</span> <span class="o">|</span><span class="n">ability</span><span class="o">|</span>
      <span class="n">ability</span><span class="p">.</span><span class="nf">can?</span><span class="p">(</span><span class="n">action</span><span class="p">,</span> <span class="n">object</span><span class="p">)</span>
    <span class="k">end</span>

    <span class="n">description</span> <span class="k">do</span>
      <span class="s2">"be able to </span><span class="si">#{</span><span class="n">action</span><span class="si">}</span><span class="s2"> -- </span><span class="si">#{</span><span class="n">object</span><span class="p">.</span><span class="nf">class</span><span class="p">.</span><span class="nf">name</span><span class="si">}</span><span class="s2">"</span>
    <span class="k">end</span>

    <span class="n">failure_message</span> <span class="k">do</span> <span class="o">|</span><span class="n">ability</span><span class="o">|</span>
      <span class="s2">"expected </span><span class="si">#{</span><span class="n">ability</span><span class="p">.</span><span class="nf">class</span><span class="p">.</span><span class="nf">name</span><span class="si">}</span><span class="s2"> to be able to </span><span class="si">#{</span><span class="n">action</span><span class="si">}</span><span class="s2"> -- </span><span class="si">#{</span><span class="n">object</span><span class="p">.</span><span class="nf">class</span><span class="p">.</span><span class="nf">name</span><span class="si">}</span><span class="s2">"</span>
    <span class="k">end</span>

    <span class="n">failure_message_when_negated</span> <span class="k">do</span> <span class="o">|</span><span class="n">ability</span><span class="o">|</span>
      <span class="s2">"expected </span><span class="si">#{</span><span class="n">ability</span><span class="p">.</span><span class="nf">class</span><span class="p">.</span><span class="nf">name</span><span class="si">}</span><span class="s2"> NOT to be able to </span><span class="si">#{</span><span class="n">action</span><span class="si">}</span><span class="s2"> -- </span><span class="si">#{</span><span class="n">object</span><span class="p">.</span><span class="nf">class</span><span class="p">.</span><span class="nf">name</span><span class="si">}</span><span class="s2">"</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="no">RSpec</span><span class="p">.</span><span class="nf">configure</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span>
  <span class="n">config</span><span class="p">.</span><span class="nf">include</span> <span class="no">AbilityHelper</span>
<span class="k">end</span>

</code></pre></div></div>

<p>We first set up a user – in this case it’s an admin user – and then initialize our ability object with this user. We further have a model called <code class="language-plaintext highlighter-rouge">AcceptanceMode</code>, which offers the usual CRUD operations. An acceptance mode has many policies. If any policy is attached to an acceptance mode, we don’t want to allow it to be deleted.</p>

<p>Note that a lot of models are <code class="language-plaintext highlighter-rouge">created</code>, meaning these are persisted to the database. In this excerpt, we have 4 test cases. Each of these test cases needs to create the admin user, acceptance mode and also create a policy. This is a lot of persisted models, even more so if you realize that this is not all the acceptance mode specs and acceptance mode specs are only a small fraction of the whole ability spec. Other models are even more complex and require more tests for other dependencies.</p>

<p>But is this really necessary? Do we really need to persist the models or could we work with in-memory versions of these?</p>

<p>Let’s take a look at this modified spec:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">describe</span> <span class="no">Ability</span> <span class="k">do</span>
  <span class="n">let</span><span class="p">(</span><span class="ss">:stub_policy</span><span class="p">)</span> <span class="p">{</span> <span class="no">Policy</span><span class="p">.</span><span class="nf">new</span> <span class="p">}</span>
  <span class="n">let!</span><span class="p">(</span><span class="ss">:admin_user</span><span class="p">)</span> <span class="p">{</span> <span class="n">build</span><span class="p">(</span><span class="ss">:admin_user</span><span class="p">)</span> <span class="p">}</span>
  <span class="n">subject!</span><span class="p">(</span><span class="ss">:ability</span><span class="p">)</span> <span class="p">{</span> <span class="no">Ability</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">admin_user</span><span class="p">)</span> <span class="p">}</span>

  <span class="n">context</span> <span class="s2">"acceptance mode"</span> <span class="k">do</span>
    <span class="n">let</span><span class="p">(</span><span class="ss">:acceptance_mode</span><span class="p">)</span> <span class="p">{</span> <span class="n">build</span><span class="p">(</span><span class="ss">:acceptance_mode</span><span class="p">,</span> <span class="ss">:policies</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="n">stub_policy</span><span class="p">])</span> <span class="p">}</span>

    <span class="p">[</span><span class="ss">:read</span><span class="p">,</span> <span class="ss">:create</span><span class="p">,</span> <span class="ss">:update</span><span class="p">].</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">action</span><span class="o">|</span>
      <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_able_to</span><span class="p">(</span><span class="n">action</span><span class="p">,</span> <span class="n">acceptance_mode</span><span class="p">)</span> <span class="p">}</span>
    <span class="k">end</span>

    <span class="n">it</span> <span class="p">{</span> <span class="n">should_not</span> <span class="n">be_able_to</span><span class="p">(</span><span class="ss">:destroy</span><span class="p">,</span> <span class="n">acceptance_mode</span><span class="p">)</span> <span class="p">}</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Note that all the <code class="language-plaintext highlighter-rouge">create</code> calls are replaced with <code class="language-plaintext highlighter-rouge">build</code>. We actually don’t need the models to be persisted to the database. The ability mainly checks if the user has admin rights (with <code class="language-plaintext highlighter-rouge">admin?</code>), which can be tested with an in-memory version of a user. Further, the acceptance mode can be built with an array that contains an in-memory stub policy. If you look closely at the <code class="language-plaintext highlighter-rouge">Ability</code> implementation, you will see that that’s not even necessary. Any object could reside in the array and the spec would still pass. But we decided to use an in-memory policy nonetheless.</p>

<p>With this approach, no model is persisted to the database. All models are in-memory but still collaborate the same way as they would have when loaded from the database first. However, no time is wasted on the database. The whole ability spec run time was reduced from 60 seconds to 5 seconds, by simply avoiding to persist models to the database in the test setup.</p>

<p>As an aside: there’s a lot of <a href="http://brandonhilkert.com/blog/7-reasons-why-im-sticking-with-minitest-and-fixtures-in-rails/">discussions</a> around the topic of factories and fixtures. Fixtures load a fixed set of data into the database at the start of the test suite, which avoids these kinds of problems entirely.</p>

<p>That’s it. We hope you can re-visit some of your slow unit tests and try to use in-memory models, or avoid persisting your models for the next unit test you write!</p>]]></content><author><name>Thomas Ritter</name></author><category term="rails" /><category term="specs" /><category term="factories" /><summary type="html"><![CDATA[We are using cancancan as an authorization gem for one of our applications. To make sure that our authorization rules are correct, we unit-tested the Ability object. In the beginning, the test was quite fast, but the more rules we added, the longer it took to run the whole model test.]]></summary></entry><entry><title type="html">Neglected ActiveRecord Features</title><link href="https://www.nethad.io/2014/10/21/neglected-active-record-features/" rel="alternate" type="text/html" title="Neglected ActiveRecord Features" /><published>2014-10-21T00:00:00+02:00</published><updated>2014-10-21T00:00:00+02:00</updated><id>https://www.nethad.io/2014/10/21/neglected-active-record-features</id><content type="html" xml:base="https://www.nethad.io/2014/10/21/neglected-active-record-features/"><![CDATA[<p>As Rails developers, we’re constantly using ActiveRecord, but are mostly using the same subset of methods and features it provides. Some of its lesser known and lesser used features could help you write cleaner code in the future and delight your co-workers. So let’s dive right in!</p>

<h4 id="pluck">Pluck</h4>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> <span class="n">user_ids</span> <span class="o">=</span> <span class="no">User</span><span class="p">.</span><span class="nf">limit</span><span class="p">(</span><span class="mi">5</span><span class="p">).</span><span class="nf">pluck</span><span class="p">(</span><span class="ss">:id</span><span class="p">)</span>
  <span class="p">(</span><span class="mf">0.5</span><span class="n">ms</span><span class="p">)</span> <span class="no">SELECT</span> <span class="s2">"users"</span><span class="o">.</span><span class="s2">"id"</span> <span class="no">FROM</span> <span class="s2">"users"</span> <span class="no">ORDER</span> <span class="no">BY</span> <span class="s2">"users"</span><span class="o">.</span><span class="s2">"name"</span> <span class="no">ASC</span> <span class="no">LIMIT</span> <span class="mi">5</span>
<span class="o">=&gt;</span> <span class="p">[</span><span class="mi">856</span><span class="p">,</span> <span class="mi">857</span><span class="p">,</span> <span class="mi">858</span><span class="p">,</span> <span class="mi">850</span><span class="p">,</span> <span class="mi">852</span><span class="p">]</span>
</code></pre></div></div>

<p>Instead of calling <code class="language-plaintext highlighter-rouge">map</code> on ActiveRecord objects, use <code class="language-plaintext highlighter-rouge">pluck</code> if you only need a list of attributes. It avoids building ActiveRecord model objects and is a lot more efficient for larger collections.</p>

<h4 id="array-arguments">Array Arguments</h4>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> <span class="no">Post</span><span class="p">.</span><span class="nf">where</span><span class="p">(</span><span class="ss">:user_id</span> <span class="o">=&gt;</span> <span class="n">user_ids</span><span class="p">).</span><span class="nf">count</span>
  <span class="p">(</span><span class="mf">5.2</span><span class="n">ms</span><span class="p">)</span> <span class="no">SELECT</span> <span class="no">COUNT</span><span class="p">(</span><span class="o">*</span> <span class="p">)</span> <span class="no">FROM</span> <span class="s2">"posts"</span> <span class="no">WHERE</span> <span class="s2">"posts"</span><span class="o">.</span><span class="s2">"user_id"</span> <span class="no">IN</span> <span class="p">(</span><span class="mi">856</span><span class="p">,</span> <span class="mi">857</span><span class="p">,</span> <span class="mi">858</span><span class="p">,</span> <span class="mi">850</span><span class="p">,</span> <span class="mi">852</span><span class="p">)</span>
<span class="o">=&gt;</span> <span class="mi">286</span>
</code></pre></div></div>

<p>You can provide an array argument for the <code class="language-plaintext highlighter-rouge">where</code> clause, which is translated to an SQL <code class="language-plaintext highlighter-rouge">IN</code>.</p>

<h4 id="where-and-not">Where and Not</h4>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> <span class="no">Post</span><span class="p">.</span><span class="nf">count</span>
  <span class="p">(</span><span class="mf">0.6</span><span class="n">ms</span><span class="p">)</span>  <span class="no">SELECT</span> <span class="no">COUNT</span><span class="p">(</span><span class="o">*</span> <span class="p">)</span> <span class="no">FROM</span> <span class="s2">"posts"</span>
<span class="o">=&gt;</span> <span class="mi">1120</span>
<span class="o">&gt;</span> <span class="no">Post</span><span class="p">.</span><span class="nf">where</span><span class="p">(</span><span class="ss">:category</span> <span class="o">=&gt;</span> <span class="s1">'rails'</span><span class="p">).</span><span class="nf">count</span>
  <span class="p">(</span><span class="mf">0.8</span><span class="n">ms</span><span class="p">)</span>  <span class="no">SELECT</span> <span class="no">COUNT</span><span class="p">(</span><span class="o">*</span> <span class="p">)</span> <span class="no">FROM</span> <span class="s2">"posts"</span>  <span class="no">WHERE</span> <span class="s2">"posts"</span><span class="o">.</span><span class="s2">"category"</span> <span class="o">=</span> <span class="s1">'rails'</span>
<span class="o">=&gt;</span> <span class="mi">295</span>
<span class="o">&gt;</span> <span class="no">Post</span><span class="p">.</span><span class="nf">where</span><span class="p">.</span><span class="nf">not</span><span class="p">(</span><span class="ss">:category</span> <span class="o">=&gt;</span> <span class="s1">'rails'</span><span class="p">).</span><span class="nf">count</span>
  <span class="p">(</span><span class="mf">0.9</span><span class="n">ms</span><span class="p">)</span>  <span class="no">SELECT</span> <span class="no">COUNT</span><span class="p">(</span><span class="o">*</span> <span class="p">)</span> <span class="no">FROM</span> <span class="s2">"posts"</span>  <span class="no">WHERE</span> <span class="p">(</span><span class="s2">"posts"</span><span class="o">.</span><span class="s2">"category"</span> <span class="o">!=</span> <span class="s1">'rails'</span><span class="p">)</span>
<span class="o">=&gt;</span> <span class="mi">825</span>
</code></pre></div></div>

<p>Using <code class="language-plaintext highlighter-rouge">where.not</code> will test for inequality, where you might have used <code class="language-plaintext highlighter-rouge">where('category != ?', 'rails')</code> in the past. This was introduced with Rails 4.0.</p>

<h4 id="ranges">Ranges</h4>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> <span class="n">date_start</span> <span class="o">=</span> <span class="no">Date</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2013</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="o">=&gt;</span> <span class="no">Tue</span><span class="p">,</span> <span class="mo">01</span> <span class="no">Jan</span> <span class="mi">2013</span>
<span class="o">&gt;</span> <span class="n">date_end</span> <span class="o">=</span> <span class="no">Date</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2013</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="o">=&gt;</span> <span class="no">Fri</span><span class="p">,</span> <span class="mo">01</span> <span class="no">Feb</span> <span class="mi">2013</span>
<span class="o">&gt;</span> <span class="nb">puts</span> <span class="no">Post</span><span class="p">.</span><span class="nf">where</span><span class="p">(</span><span class="ss">:published_on</span> <span class="o">=&gt;</span> <span class="n">date_start</span><span class="o">..</span><span class="n">date_end</span><span class="p">).</span><span class="nf">to_sql</span>
<span class="no">SELECT</span> <span class="s2">"posts"</span><span class="p">.</span><span class="nf">*</span> <span class="no">FROM</span> <span class="s2">"posts"</span>  <span class="no">WHERE</span> <span class="p">(</span><span class="s2">"posts"</span><span class="o">.</span><span class="s2">"published_on"</span> <span class="no">BETWEEN</span> <span class="s1">'2013-01-01'</span> <span class="no">AND</span> <span class="s1">'2013-02-01'</span><span class="p">)</span>
</code></pre></div></div>

<p>Where clauses also support ranges. In the example above we see a ruby date range that gets elegantly translated
to SQL <code class="language-plaintext highlighter-rouge">BETWEEN</code> syntax.</p>

<h4 id="order">Order</h4>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> <span class="nb">puts</span> <span class="no">Post</span><span class="p">.</span><span class="nf">unscoped</span><span class="p">.</span><span class="nf">order</span><span class="p">(</span><span class="ss">:published_on</span> <span class="o">=&gt;</span> <span class="ss">:asc</span><span class="p">).</span><span class="nf">to_sql</span>
<span class="no">SELECT</span> <span class="s2">"posts"</span><span class="p">.</span><span class="nf">*</span> <span class="no">FROM</span> <span class="s2">"posts"</span>   <span class="no">ORDER</span> <span class="no">BY</span> <span class="s2">"posts"</span><span class="o">.</span><span class="s2">"published_on"</span> <span class="no">ASC</span>
<span class="o">=&gt;</span> <span class="kp">nil</span>
<span class="o">&gt;</span> <span class="nb">puts</span> <span class="no">Post</span><span class="p">.</span><span class="nf">unscoped</span><span class="p">.</span><span class="nf">order</span><span class="p">(</span><span class="ss">:published_on</span> <span class="o">=&gt;</span> <span class="ss">:desc</span><span class="p">).</span><span class="nf">to_sql</span>
<span class="no">SELECT</span> <span class="s2">"posts"</span><span class="p">.</span><span class="nf">*</span> <span class="no">FROM</span> <span class="s2">"posts"</span>   <span class="no">ORDER</span> <span class="no">BY</span> <span class="s2">"posts"</span><span class="o">.</span><span class="s2">"published_on"</span> <span class="no">DESC</span>
<span class="o">=&gt;</span> <span class="kp">nil</span>
</code></pre></div></div>

<p>Instead of the using the <code class="language-plaintext highlighter-rouge">order</code> argument with a string as <code class="language-plaintext highlighter-rouge">order("published_on DESC")</code>, you can simply pass a hash.</p>

<h4 id="discarding-from-the-chain">Discarding From The Chain</h4>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> <span class="nb">puts</span> <span class="no">Post</span><span class="p">.</span><span class="nf">unscoped</span><span class="p">.</span><span class="nf">order</span><span class="p">(</span><span class="ss">:published_on</span> <span class="o">=&gt;</span> <span class="ss">:desc</span><span class="p">).</span><span class="nf">except</span><span class="p">(</span><span class="ss">:order</span><span class="p">).</span><span class="nf">to_sql</span>
<span class="no">SELECT</span> <span class="s2">"posts"</span><span class="p">.</span><span class="nf">*</span> <span class="no">FROM</span> <span class="s2">"posts"</span>
</code></pre></div></div>

<p>With the <code class="language-plaintext highlighter-rouge">expect</code> syntax you can get rid of clauses to the ActiveRecord relation that were added before. This could
come in handy if you’re given a base scope that is valid for all cases except yours and avoids throwing away any other modifications to the relation.</p>

<h4 id="the-null-relation">The Null Relation</h4>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> <span class="no">Post</span><span class="p">.</span><span class="nf">none</span><span class="p">.</span><span class="nf">where</span><span class="p">(</span><span class="ss">:category</span> <span class="o">=&gt;</span> <span class="s2">"rails"</span><span class="p">)</span>
<span class="o">=&gt;</span> <span class="p">[]</span>
</code></pre></div></div>

<p>This feature might look like non-sense at first. The <code class="language-plaintext highlighter-rouge">none</code> clause makes sure that whatever clause is added to the relation, the result will always be empty. Again, this might make sense if you are provided with a relation and have to return one again. Say now we have a case where the current query is not valid due to permission constraints. Adding the <code class="language-plaintext highlighter-rouge">none</code> clause makes sure that whatever relation modification follows, the final query will not hit the database and will be empty.</p>

<h4 id="readonly">Readonly</h4>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">post</span> <span class="o">=</span> <span class="no">Post</span><span class="p">.</span><span class="nf">readonly</span><span class="p">.</span><span class="nf">first</span>
<span class="n">post</span><span class="p">.</span><span class="nf">title</span> <span class="o">=</span> <span class="s2">"Don't change me!"</span>
<span class="n">post</span><span class="p">.</span><span class="nf">save!</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">readonly</code> clause makes sure that a relation cannot be modified. This might make sense if you pass an object to any code that is not yours (e.g. a library) and want to make sure that the object is not modified.</p>

<h4 id="summary">Summary</h4>

<p>So that’s it. I hope you can use some of these tricks to not only make your code faster and more elegant, but also more readable.</p>]]></content><author><name>Thomas Ritter</name></author><category term="rails" /><category term="activerecord" /><category term="neglected" /><summary type="html"><![CDATA[As Rails developers, we’re constantly using ActiveRecord, but are mostly using the same subset of methods and features it provides. Some of its lesser known and lesser used features could help you write cleaner code in the future and delight your co-workers. So let’s dive right in!]]></summary></entry><entry><title type="html">Android tools prefix</title><link href="https://www.nethad.io/2014/10/12/android-tools-prefix/" rel="alternate" type="text/html" title="Android tools prefix" /><published>2014-10-12T00:00:00+02:00</published><updated>2014-10-12T00:00:00+02:00</updated><id>https://www.nethad.io/2014/10/12/android-tools-prefix</id><content type="html" xml:base="https://www.nethad.io/2014/10/12/android-tools-prefix/"><![CDATA[<p>When implementing views in Android, you oftentimes want to have values that are only meant to render nicely in the layout designer.</p>

<p>This is where the <code class="language-plaintext highlighter-rouge">tools:</code> prefix comes in handy!</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;TextView</span>
  <span class="na">android:id=</span><span class="s">"@+id/someLabel"</span>
  <span class="na">style=</span><span class="s">"@style/Text.Label"</span>
  <span class="na">android:layout_width=</span><span class="s">"wrap_content"</span>
  <span class="na">android:layout_height=</span><span class="s">"wrap_content"</span>

  <span class="na">tools:text=</span><span class="s">"@string/some_string"</span>
  <span class="nt">/&gt;</span>

<span class="nt">&lt;ListView</span>
  <span class="na">android:id=</span><span class="s">"@+id/someList"</span>
  <span class="na">android:layout_width=</span><span class="s">"match_parent"</span>
  <span class="na">android:layout_height=</span><span class="s">"match_parent"</span>

  <span class="na">tools:listitem=</span><span class="s">"@android:layout/simple_list_item_2"</span>
  <span class="nt">/&gt;</span>
</code></pre></div></div>

<p>In the first text view you can see a text attribute (<code class="language-plaintext highlighter-rouge">tools:text</code>) that is only visible in the layout designer. This way, you
can provide a sample text that will render nicely in the designer, but not accidentally expose sample texts in your actual application.</p>

<p>In the list view, the <code class="language-plaintext highlighter-rouge">tools:listitem</code> directive specifies a layout which the list view items should use. This way, your list views are pre-filled with sample items in the designer. If you also use the <code class="language-plaintext highlighter-rouge">tools</code> directives in your list item layout, the pre-filled items will use them as well.</p>

<p>You can use almost any <code class="language-plaintext highlighter-rouge">android</code> attribute and replace it with <code class="language-plaintext highlighter-rouge">tools</code> to have design-time attributes. In fact, if you provide attributes with both prefixes, the <code class="language-plaintext highlighter-rouge">tools</code> prefix is valid during design-time, while your actual <code class="language-plaintext highlighter-rouge">android</code> attribute is used during runtime.</p>

<p>You can find more information in the <a href="http://tools.android.com/tech-docs/tools-attributes">official documentation</a>.</p>]]></content><author><name>Thomas Ritter</name></author><category term="android" /><category term="xml" /><category term="designer" /><summary type="html"><![CDATA[When implementing views in Android, you oftentimes want to have values that are only meant to render nicely in the layout designer.]]></summary></entry></feed>