Using Terminal Better I – ls and mv

Learning to navigate the terminal is definitely a part of learning to be a developer, so I wanted to share a few commands that have proven especially useful and important to me. Today’s post deals with ls and mv. Note that each command can be passed “flags”, i.e. parameters.

To navigate directories: One . indicates the current directory and .. takes you one level higher. So cd .. will navigate you one level up and cd ./../.. or cd ../.. will navigate you two levels up.

ls

ls lists all files in the current directory, but results can be displayed in a ton of different ways using different flags. ls -al displays results in a data table with relevant info (modification date, file name, etc.), and you can also decide how you want results sorted. ls -t sorts results by most recently modified first, and ls -tr sorts by most recent modified file last. You can append multiple flags: ls -al -t returns results in a data table ordered by recently modified first.

mv

mv is a clever move function that also accepts flags and can be used for a variety of other purposes, such as renaming directories. mv is quite powerful, so it’s a good idea to use the flag -i in order to ask you before deleting anything.

Let’s say I want to rename my book report from “draft.doc” to “final.doc”. I can use the mv to move the contents of “draft.doc” into a new file automatically created called “final.doc”, automatically deleting the old file, using the following syntax: mv draft.doc final.doc. If you specify a directory to move to, the file will move to that directory. If you specify a directory and filename to move it, the file will be moved and renamed to the new filename.

3 steps to File Uploading using Carrierwave

Adding a file upload feature to an app is fairly simple with the popular Carrierwave gem. And commercial file hosting is seamless as well with Amazon’s Simple Storage Service (S3), which plays very nicely with Carrierwave. I’ll cover S3 integration in a later post.

I’ve broken down the process into 3 easy steps:

1. Add a file upload field in your view and a column to your model

The first step is to implement a file upload field in a form on your app:

form_for .... do
  = f.file_field :passport_picture
f.submit "Submit"

You need a column called “passport_picture” in your model, so generate a migration and add in that column.

We used a popular gem called Carrierwave to handle the file uploading, so let’s add it and its associated gems to the Gemfile:

gem 'carrierwave'
gem "fog", "~> 1.3.1"
gem 'mini_magick'

2. Make uploader classes for each file

Now we need to make an uploader class that contains uploading instructions. Our uploader will instruct Carrierwave to use the MiniMagick gem for image processing (optional):
app/uploaders/passport_picture_uploader.rb

class PassportPictureUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  store: file

 process :resize_to_fill => [200, 200]
end

One caveat here: you need to make sure ImageMagick is installed on your computer, and this was not easy for me. You can install it using Homebrew or Rvm if you don’t have it, but google around for more specific instructions.

3. Mount the uploaders in your model

Now you need to tell your model to mount the uploader(s):

class User < ActiveRecord::Base
  mount_uploader :passport_picture, PassportPictureUploader
end

And that’s it!

As an aside, I think this would be a good candidate to shuffle off to a background process so that the user doesn’t have to wait until the file uploads for the form to submit. I’ll talk about what I’ve learned about background processes in a later post.

Namespacing Models

Namespacing can be used to add a new actor to an application – an Admin, who has special access, for instance.

Let’s say we want to have a Users Controller that is accessible only by admins. To do this, we route requests to a Users Controller through the Admin namespace (generating a route of /admin/users/):

namespace :admin do
  resources :users
end

Rails generates a path of/admin/users and a helper of admin_users, a path of /admin/users/new and a helper of new_admin_user, etc.

And now we need a new Users controller that we place in the app/controllers/admin directory.

Solution 1 – Regular Namespaced Controller

The simplest way to add in the new Admin actor is to create a new users_controller.rb in that directory, have it inherit from the Application Controller like a regular controller, and include an appropriate before_filter defined in the ApplicationController that will ensure that a user accessing any actions from that controller is an admin:

class Admin::UsersController < ApplicationController
 before_filter :ensure_admin

However, this is not the most efficient solution for larger apps where many controllers will be delegated to the Admin namespace – every controller would need to include the before_filter :ensure_admin line, which is not very DRY.

Solution 2 – Inheriting from an AdminsController

A more efficient way to do it is by having each namespaced class inherit from a separate Admin class, which itself inherits from ApplicationController and includes the before_filter. That way every inheriting subclass will require admin authorization:
app/controllers/admin/users_controller.rb

class Admin::UsersController < AdminsController

  def create
  end

end

app/controllers/admins_controller.rb

class AdminsController < ApplicationController
  before_filter :ensure_admin
  def ensure_admin
  ....
  end
end

Namespacing can be used to add any actor with particular access – a merchant, customer, admin, guest, etc. And actors can inherit from each other in order to share privileges as well.

Now if you want to submit a model-backed form to a namespaced model, the syntax is similar to nested resources:

form_for [:admin, @user] do
...

Testing with Selenium

When doing feature testing with the Capybara gem, you use racktest as the default testing driver. Racktest is fast, as it’s a headless driver – it simulates the browser experience without firing up an actual browser. But if you need javascript, you need to use either Selenium, which actually fires up Firefox and simulates the entire user flow before your eyes, or Capybara WebKit, another headless driver that is faster than Selenium, but supports js.

Once you’ve configured Capybara, invoking selenium just requires that you set “js: true” explicitly after a feature / describe line (depending on whether you decide to use Capybara’s DSL or the regular Rspec syntax). Example:

feature 'User interacts with the queue', js: true do

For this to work, you need to disable transactional_fixtures, a feature offered by rspec that opens a database transaction at the beginning of a test, and then rolls it back at the end. This feature does not work with Capybara javascript tests, so disable it by placing self.use_transactional_fixtures = false after the feature/describe line (again, capybara dsl vs. rspec distinction) and before the scenario/it line.

If you want the firefox browser window to stop so that you can play with one of the pages, you can drop a <code>sleep [x seconds]</code> command anywhere in the test and the browser will wait for the specified time before continuing on its way (and then closing if it’s the end of the test).

Pushing to Github from a Cafe

I do most of my programming from cafes and until today I’ve faced a major annoyance – a lot of public wifis are configured to block ssh access. Unfortunately this is how I connect with Github, so I haven’t able to push any code changes while working at the cafes.

Today I found a fix for this on StackOverflow, quoting this article from Github – all you need to do is configure your computer to use port 443 for GitHub access, which is the default HTTPS port and is usually not blocked. Essentially you’re making an SSH connection over the port generally used for HTTPS.

1. Test to see whether you can make SSH connections over the HTTPS port. In the terminal, run:

$ ssh -T -p 443 git@ssh.github.com

You should get the following response:
Hi username! You’ve successfully authenticated, but GitHub does not provide shell access.

2. Open ‘~/.ssh/config’ using your text editor (I use Sublime Text 2):

subl ~/.ssh/config

3. Paste in the following:

Host github.com
Hostname ssh.github.com
Port 443

4. Test that it works: $ ssh -T git@github.com
You should get the following response:
Hi username! You’ve successfully authenticated, but GitHub does not
provide shell access.

And that’s it. Now you should be able to work with Git in public places. What I am curious about is whether there are security issues when doing this, and how to make it work for heroku as well. I guess that’ll be for a future post.

Testing is not bad at all.

Last week I bought the “Everyday Rails Testing with Rspec” book by Aaron Sumner for the third Ruby on Rails course by the TeaLeaf Academy (which, by the way, is a lot of fun!). I expected testing to be a bit of a chore, but it turns out that I’m actually enjoying it.

The course introduces testing very gradually, so that in each exercise you just focus on one or two tests. It’s basically breaking up a new skill into edible chunks so that you can really focus on each chunk and process it properly until you understand it. Testing presents kind of a fun brain challenge, figuring out exactly which cases you want to test for and how to most accurately test for these cases, and at the same time it gives you a better understanding of what’s going on in your own app.