Dynamic select boxes with Rails 4

PareidoliaX:

Great Tutorial with Demo. Love the format.

Originally posted on Kernel Garden:

Introduction

I recently started doing some Rails development for a personal project (a wine cellar manager). I wanted to add a new wine to the database such that choosing the new wine’s country should update the list of available appellations to pick out for that country. The appellations are stored into the database and each appellation belongs to a country.

It turns out I did not find much info about that kind of feature; and most tutorials were either over-complicated stuff with a lot of JavaScript, or just outdated material targeting Rails 2 or 3.

Finally I thought that was a good opportunity to understand more deeply how a Rails application is constructed. At the time of writing, I used Rails 4 and Ruby 2.0. I tried to stick as much as possible to the Rails precept: convention over configuration. I don’t use any extra gems, and the code comes…

View original 691 more words

My Sublime Settings

Occasionally I like to post my configuration both for vanity and easy of reference when I am setting up new development environments. I am still using Sublime Text 2 as my text editor of choice. Here are my keybindings and user settings.

Key Bindings

// Mac
[
{ "keys": ["ctrl+shift+."], "command": "erb" },
{ "keys": ["ctrl+i"], "command": "expand_tabs" },
// swap the keybindings for paste and paste_and_indent
{ "keys": ["super+v"], "command": "paste_and_indent" },
{ "keys": ["super+shift+v"], "command": "paste" }
]

// Windows / Linux
[
{ "keys": ["ctrl+shift+."], "command": "erb" },
{ "keys": ["alt+i"], "command": "expand_tabs" },
// swap the keybindings for paste and paste_and_indent
{ "keys": ["ctrl+v"], "command": "paste_and_indent" },
{ "keys": ["ctrl+shift+v"], "command": "paste" }
]

Expand tabs is the command to convert any hard tabs into spaces, super useful if you are working on a code base where someone has been using hard tabs when they shouldn’t have.

Sublime Text has paste with smart indentation which is more often than not the behaviour you want when pasting in code. These key binds swap the short cut for simple paste with the shortcut for paste with smart indentation.

User Settings

{
"color_scheme": "Packages/Color Scheme – Default/Cobalt.tmTheme",
"draw_white_space": "all",
"font_size": 18.0,
"tab_size": 2,
"translate_tabs_to_spaces": true,
"word_wrap": false
}

For peace of mind I always like to see the white space in my code files. That way, when my code is broke and I don’t know why at least one usual suspect is already marked off the list. Also I don’t like word wrap as a default for code. Sometimes it is useful, so sometimes I turn it on but as I default, I like it off.

Git for Windows tip: opening Sublime Text from bash

PareidoliaX:

I found lots of ways to setup sublime text 2 in Git Bash online, but this is by far the quickest and easiest.

Originally posted on danlimerick:

I wrote a post about how to open NotePad++ from the bash prompt a few years ago but I recently made the switch to using Sublime Text 2 as my standard text editor and had to figure out how to do the same thing with Sublime. It was surprisingly difficult to find it on Google.

1. Create a text file called subl (with no extension) with the following content:

2.  copy it into the C:Program Files (x86)Gitbin folder.

The first line indicates that this is a shell script. The first part of the second line is the path to the Sublime exe. The $1 parameter passes in any parameters so that you can use it like this from the bash prompt (command line) to open a file:

or

to open the current folder.

The last parameter & indicates that it should open Sublime in the background so that you can…

View original 5 more words

Sublime Text 2 on OSX Terminal Command Line Setup

Sublime Text 2 is a great text editor. I recommend it for beginners learning to code. However setting up some of the key features, like using it on the command line, are text-based command heavy. I found the documentation to setup Sublime Text 2 in OSX assumes you know a fair bit about bash and Unix/Linux file structures. Most Mac users who want to learn programming don’t know this stuff. In this blog post I will provide supplementary documentation. Here are a set of bash commands, if run in order, they will setup Sublime Text 2 to work on the terminal command line for almost all OSX users.

sublime_setup.sh

mkdir ~/bin
touch ~/.bash_profile
echo 'export PATH="~/bin:$PATH"' >> ~/.bash_profile
echo "export EDITOR='subl -w'" >> ~/.bash_profile
ln -s "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl" ~/bin/subl
source ~/.bash_profile

I Remember Now, Python is Awesome!

I’ve been brushing off my rusty Python skills this week by doing a Introductory Python course on Treehouse. I’m doing this because of the impressive things I’ve seen Cam Davidson-Pilon do with iPython.

Behold the fruits of my labour! A simple text based guessing game.

guessing_game.py

import random
 
def show_guesses():
  guesses.append(guess)
  print(str(guesses) + " {} more out of 5.".format(5 - len(guesses)))
 
def show_help():
  print("Guess a number between '1' and '10'")
  print("'DONE' quits and 'HELP' displays this help.")
 
def too_big():
  print("{} is too big".format(guess))
 
def too_small():
  print("{} is too small".format(guess))
  
def reset_game():
  global guesses
  global magic_num
  guesses = []
  magic_num = random.randint(1,10)
  print("Okay, ready! I've picked a number.")
  
 
guesses = []
magic_num = 0
reset_game()
show_help()
 
while True:
  if len(guesses) >= 5:
    print("Sorry, you lose. The number was {}.".format(magic_num))
    reset_game()
  response = input("> ")
  
  try:
    guess = int(response)
  except:
    if response == 'DONE':
      break
    elif response == 'HELP':
      show_help()
      continue
      
  if guess == magic_num:
    print("That's it! The number was {}. You win! Play again? (Y/n)".format(guess))
    play_again = input('> ')
    if play_again == 'n':
      break
    else:
      reset_game()
  elif int(guess) > magic_num:
    too_big()
    show_guesses()
  elif int(guess) < magic_num:
    too_small()
    show_guesses()
  continue

DRY Social Media Links

I went a little crazy with social media links last night. I wanted to make a nice nav element full of them. First I found a great github repository and site for the images called simpleicons.org.

With all those great icon options I ended up wanting to make nine links but I wanted to keep things DRY so I used an array and a loop. I was pretty pleased with the result.

_footer.html.erb

<footer>
  <% social_media = [
    ["Github", "github-256.png", "https://github.com/PareidoliaX"],
    ["LinkedIn", "linkedin-256.png", "https://www.linkedin.com/pub/alexander-miller/2b/909/62b"],
    ["CodeSchool", "codeschool-256.png", "https://www.codeschool.com/users/336826"],
    ["Treehouse", "treehouse-256.png", "http://teamtreehouse.com/alexandermiller"],
    ["Khan Academy", "khanacademy-256.png", "https://www.khanacademy.org/profile/PareidoliaX/"],
    ["WordPress", "wordpress-256.png", "http://pareidoliax.ca/"],
    ["Steam", "steam-256.png", "http://steamcommunity.com/profiles/76561198025305101"],
    ["Twitter", "twitter-256.png", "https://twitter.com/PareidoliaX"],
    ["Facebook", "facebook-256.png", "https://www.facebook.com/xander.miller"]
    ] %>
    <div class="row">
      <nav>
        <ul id="social-media">
          <% social_media.each do |media| %>
            <li>
              <%= link_to media[2] { image_tag("https://s3-us-west-2.amazonaws.com/xander-mind/#{media[1]}", alt: "#{media[0]} Logo")} %>
            </li>
          <% end %>
        </ul>
      </nav>
    </div>
  <div class="row">
    <p class="text-right">&copy; 2014 <em>Xander Miller</em></p>
  </div>
</footer>

This code is available in a github gist for easy copying. Happy Coding!

Making a Dynamic Navigation in your Rails 4 layout

Often it is helpful to have an indication on your site navigation of where you currently are. For example if you are on the About page, then the About button in the navigation should be a different colour than the other navigation buttons. On a static website this is easily done with a css class like selected or active. Here is the example of how it is done with the Twitter bootstrap design framework using the active class.

<ul class="nav nav-pills">
  <li class="active"><a href="#">Home</a></li>
  <li><a href="#">Profile</a></li>
  <li><a href="#">Messages</a></li>
</ul>

This is easy to accomplish on a static page. Just change the navigation accordingly on each page but things can be a bit more complicated when using a dynamic framework like Rails. In Rails your site navigation will be in your main layout so you need to make that navigation dynamically sensitive to controller and action that rendered it. You can do this with some helper methods. I’m going to be using Rails 4 helper methods but this can be done easily using more obscure methods in earlier versions of Rails. There is no helper method to my knowledge in Rails that gives you both the controller and the action so we are going to start by building that from the helpers that give use the controller name and the action name.

We need both because if we are using RESTful resource routes neither the controller or the action by themselves will uniquely identify a view. Post may have both an index and a show view so the controller alone is not enough. Comment and Post may both have show and edit actions so the action alone is not enough to identify a view either. Since we are practicing Test Driven Development, lets start with the RSpec example.

application_helper_spec.rb

# helper is an instance of ActionView::Base configured with the
# ApplicationHelper and all of Rails' built-in helpers

require "spec_helper"

describe ApplicationHelper do

  context '#controller_action_name' do
    it "calls #action_name" do
      helper.should_receive(:action_name)
      helper.controller_action_name
    end

    it 'calls #controller_name' do
      helper.should_receive(:controller_name)
      helper.controller_action_name
    end

    it 'returns a concatination of #controller_name and #action_name' do
      helper.stub(:controller_name).and_return('welcome')
      helper.stub(:action_name).and_return('about')
      helper.controller_action_name.should eq('welcome#about')
    end
  end

end

The actually helper will be a one-liner and since it will be used at the application layout level it will have to be an application level helper.

application_helper.rb

module ApplicationHelper

  def controller_action_name
    "#{controller_name}##{action_name}"
  end

end

Now that we have a helper that gives us both the controller and the action name. Lets use it to build the helper method we will use to add the active class to the appropriate element of our navigation. Again starting with the RSpec example.

application_helper_spec.rb

# helper is an instance of ActionView::Base configured with the
# ApplicationHelper and all of Rails' built-in helpers

require "spec_helper"

describe ApplicationHelper do

  context '#controller_action_name' do
    it "calls #action_name" do
      helper.should_receive(:action_name)
      helper.controller_action_name
    end

    it 'calls #controller_name' do
      helper.should_receive(:controller_name)
      helper.controller_action_name
    end

    it 'returns a concatination of #controller_name and #action_name' do
      helper.stub(:controller_name).and_return('welcome')
      helper.stub(:action_name).and_return('about')
      helper.controller_action_name.should eq('welcome#about')
    end
  end

  context "#display_active" do
    it "returns 'active' if the current controller action equals the argument" do
      helper.stub(:controller_action_name).and_return('welcome#about')
      expect(helper.display_active('welcome#about')).to match /active/
    end

    it "returns '' if the current controller action does not equal the argument" do
      helper.stub(:controller_action_name).and_return('welcome#about')
      helper.display_active('welcome#contact').should eq('')
    end
  end

end

And this method will also only be a one-liner in the application helper.

application_helper.rb

module ApplicationHelper

  def controller_action_name
    "#{controller_name}##{action_name}"
  end

  def display_active controller_action
    controller_action == controller_action_name ? "active" : ""
  end

end

Now we just use the display_active method to add a class to our app navigation like this.

_navbar.html.erb

<nav>
  <ul class="nav nav-pills">
    <%= content_tag :li, link_to("Portfolio", welcome_portfolio_path), class: display_active('welcome#portfolio') %>
    <%= content_tag :li, link_to("About", welcome_about_path), class: display_active('welcome#about') %>
    <%= content_tag :li, link_to("Contact", welcome_contact_path), class: display_active('welcome#contact') %>
  </ul>
</nav>

This example should work with bootstrap 3 but the principle should be easy to apply to Foundation or a custom design. I have put all the code snippets in a github gist for easy copying.

Keeping your RSpec Welcome Controller Spec DRY

I was writing controller specs for a personal project I started working on this week. I’m testing like the TSA because I would like the practice with RSpec. My code smell sense started tingling when I noticed myself repeatedly hitting the copy and paste short cut. Do you see the problem?

require "spec_helper"
 
RSpec.describe WelcomeController, :type => :controller do
 
  describe "GET home" do
    it "returns http success" do
      get :home
      expect(response).to be_success
    end
 
    it "renders the home template" do
      get :home
      expect(response).to render_template("home")
    end
  end
  
  describe "GET about" do
    it "returns http success" do
      get :about
      expect(response).to be_success
    end
  
    it "renders the about template" do
      get :about
      expect(response).to render_template("about")
    end
  end
  
  describe "GET contact" do
    it "returns http success" do
      get :contact
      expect(response).to be_success
    end
 
    it "renders the contact template" do
      get :contact
      expect(response).to render_template("contact")
    end
  end
 
end

I’m basically running the same two specs three times, once for each controller action so I decided to keep things DRY by using a loop instead. This is what I came up with:

require "spec_helper"
 
RSpec.describe WelcomeController, :type => :controller do
 
  welcomes = %w{portfolio about contact}
 
  welcomes.each do |welcome|
    describe "GET #{welcome}" do
      it "returns http success" do
        get welcome.to_sym
        expect(response).to be_success
      end
 
      it "renders the #{welcome} template" do
        get welcome.to_sym
        expect(response).to render_template(welcome)
      end
    end
  end
end

I’m sure this is nothing new for RSpec veterans and an even better solution would be to write my own RSpec matcher. Nonetheless I was proud of myself for coming up with this today so I decided to share. The specs are based on the examples for controllers in the rspec-rails repo and I have put the code snippets you see in this entry in a gist for easy copying and pasting.

What version of RSpec should I use?

This is the kind of blog post that goes out of date almost the day it is written, which happens to be August 6th, 2014. However not knowing the version of RSpec to use cost me two productive hours today so I thought despite the perishability, the current answer is worth mentioning. If you are starting a new Rail 4.1 app any time soon the most compatible and stable version of RSpec to use is 2.14.x, both version 2.99.x and 3.0.x aren’t well supported by other gems yet. Capybara, pundit and FactoryGirl all didn’t support rspec 3.0.x.