Last Build Date: Fri, 19 Aug 2016 13:38:12 +0200
Fri, 19 Aug 2016 13:03:11 +0200In a previous article we discussed some basic sensibilities about accessors in the controller and views, and storing authenticated sessions in your database. First we’re going to take a conceptual look at credentials and then think about a clever way to deal with them in our application. In an abstract way we share and exchange a private piece of information to identify a person. In most cases there is also a semi-public piece of information involved. We call this information the person’s credentials. Most of the times this takes the form of a password, and a username or e-mail address. People can also authenticate themselves with just a shared secret, for example: a session token, SSL certificate, Kerberos ticket, API key, OAuth token, or PIN. During login a person presents us with their credentials and we check them against our stored version. Storing credentials Don’t store plain text password. Try not to store any secrets as readable text when you don’t need to. When your accounts always have exactly one set of credentials you can store them directly on the accounts table. create_table :accounts do t.string :email t.string :encrypted_password end In a very tiny amount of cases you may store information about people separately from their accounts. Never make your database structure more complicated than it needs to be. You can always make things more complicated in the future. As explained in the previous article I don’t like calling the table users. When the focus is on the credentials I like to use accounts. If it also needs to store a lot of personal information about the person, I like people. Updating the password Rails likes to use regular accessor methods when you’re writing forms, so let’s pretend our Account has a regular password field and then make it behave in such a way that it ‘just works’. <%= form_for(@account) do |f| %> <%= f.password_field :password %> <% end %> In the model that means we need to be able to read and write the password. We add a reader for the password and the writer updates the password in our actual database field. class Account < ActiveRecord::Base attr_reader :password def password=(password) @password = password unless password.blank? self.encrypted_password = self.class.encrypt(password) end end end Note that this means that the password value will always be empty when it wasn’t set during this request. This is something we need to take into account when writing validations. class Account protected MINIMAL_PASSWORD_LENGTH = 6 def password_requirements # Nothing was set return if @password.nil? # Can't be blank if @password.blank? errors.add(:password, :blank) # Can't be too short elsif @password.to_s.length < MINIMAL_PASSWORD_LENGTH errors.add( :password, :too_short, count: MINIMAL_PASSWORD_LENGTH ) end end validate :password_requirements end Remember to add translations for the errors.messages.too_short key, otherwise it will just say ‘Password too short’. Now we need to select a nice encryption algorithm to secure the password with. I personally like SCrypt. Please be very careful to select an appropriate algorithm that fits your needs and stores the password in an acceptable way. require 'scrypt' # Automatically chooses a cost value for # its algorithms based on the speed of # the hardware used. SCrypt::Engine.calibrate class Account def self.encrypt(password) SCrypt::Password.create(password).to_s end end We also need to be able to check the password against the value in the database. class Acccount def has_password?(password) SCrypt::Password.new(encrypted_password) == password rescue SCrypt::Errors::InvalidHash, NoMethodError # When feeding an invalid value (e.g. nil or a blank) # String we want this to return false instead of # break. false end end When you have a form that updates the password and checks the old va[...]
Fri, 01 Jul 2016 09:50:17 +0200Ruby as well as Rails started out simple. Over the years however, the number of tools in use by the average Rails developer has grown steadily. Even though all of these tools serve a useful purpose, and together certainly make your life as a developer easier, it can be hard for people new to Rails to get everything up and running, and to understand how the different components interact. This guide tries to help. The components Ruby is a general purpose programming language. One of the nice things about Ruby is that it allows you to use multiple paradigms such as functional, object-oriented, and imperative programming. Ruby on Rails, often referred to simply as “Rails”, is a web application framework written in Ruby. Rails is based on the Model-View-Controller architecture, comes with sensible defaults, and favors convention over configuration. This helps you get going quickly and can make it easier to understand and modify applications written by others. RubyGems is a package manager for Ruby programs, frameworks, and libraries. An individual package is called a “Gem”. Gems are installed as part of your Ruby installation. Rails itself is distributed as a Gem. Bundler is a tool that can install all the Gems a Rails application depends on by running a single command. This works by listing all dependencies in what’s called a “Gemfile” in the root directory of the Rails application. Rbenv is a tool that allows you to set up and manage multiple separate Ruby installations. Rbenv makes it easy to use a different version of Ruby than the one that came pre-installed on your computer. It also allows you to use the exact same version of Ruby on your own computer during development as the one that’s running on your production server. You can find more information and full documentation for each of these components on the web: Ruby: http://ruby-doc.org Rails: http://rubyonrails.org/ RubyGems: http://guides.rubygems.org Bundler: http://bundler.io Rbenv: https://github.com/rbenv/rbenv Installation This guide assumes you’re using a Mac running OS X 10.11 El Capitan. Most things should also work for earlier versions of OS X as well as on Linux. It also assumes you have a text editor (such as Atom, TextMate, or Sublime Text) and that you know how to run commands in the Terminal. The purpose is not to provide the quickest way to get Rails running. Rather, this guide gives you the same setup as most developers who regularly work on Rails projects. It also helps you understand this setup and how to use and maintain it. Finally, this guide makes no permanent changes to your computer’s operating system installation by never requiring you to “sudo to root”. Homebrew We’re going to use Homebrew to install Rbenv. Homebrew is a package manager that makes it easy to install open source command line tools on OS X. First, make sure you have Xcode installed. You can get Xcode from the App Store. Go to http://brew.sh and copy the installation command at the top of the page. Open the Terminal, paste the installation command, and run it. You might get a message telling you that you haven’t yet agreed to the Xcode license. If that’s the case, open Xcode, agree to its license, and run the Homebrew installation command again. Use Homebrew to install Rbenv Run the following commands in the Terminal to install Rbenv: $ brew update $ brew install rbenv ruby-build Now open the configuration file of your shell in a text editor. This is ~/.bash_profile assuming you’re using the default Bash shell on OS X. Add the following line at the bottom: eval "$(rbenv init -)" Instead of ~/.bash_profile on OS X, you’ll probably need to edit ~/.bashrc if you’re on Linux, or ~/.zshrc if you’re using Zsh. Save your changes to the shell configuration file. Now close the Terminal, and re-open it to load the changed configuration. Run the following command: $ type rbenv This should display “rbenv is a function” followed by some more output. If you only get something like “rben[...]
Mon, 04 May 2015 18:27:15 +0200
Feature churn can really get bogged down in older Rails projects. One of the reasons is action packed controllers: the art of stacking actions on a controller that should not have those actions. Let’s look at a few ways to identify these and get rid of them.
People have adopted a number of simple guidelines to keep the scope of controllers small. One of these is only using index, new, create, show, edit, update, destroy actions on the controller. When you need any actions other than these you’re probably packing on too much functionality.
resources :books do member do delete :delete_cover end end class BooksController < ApplicationController def new @book = Book.new end def delete_cover @book = Book.find(params[:id]) if @book.cover.destroy redirect_to @book end end end
In the example above we’re packing functionality related to covers on top of the books controller.
Create a new controller specifically for the model you were operating on. Notice how this also cleans up the routes.
resources :books do resource :cover end class CoversController < ApplicationController def destroy @book = Book.find(params[:book_id]) if @book.cover.destroy redirect_to @book end end end
You might think: awesome, anyone can refactor a controller with an obvious solution but my controller is a cesspit worse than the atmosphere of Jupiter.
class BooksController < ApplicationController before_action :find_book_for_author, except: :edit_book before_action :disallow_offenders before_action :set_ccr_rules_header, only: :new layout :set_layout_for_author def delete_cover if @book.cover.destroy redirect_to @book end end private def find_book_for_author @author = Author.find(session[:current_author_id]) @book = @author.books.find(param[:id]) end # […] etc etc end
Refactoring always happens with baby steps. The solution here is to embrace the cesspit and think about fixing it later.
# Contains all methods shared by the books # and covers controller. module Concerns::BooksAndCoversControllerMethods protected def find_book_for_author @author = Author.find(session[:current_author_id]) @book = @author.books.find(book_id_param) end # […] etc etc end class CoversController < ApplicationController include Concerns::BooksAndCoversControllerMethods before_action :find_book_for_author before_action :disallow_offenders layout :set_layout_for_author def destroy if @book.cover.destroy redirect_to @book end end private def book_id_param params[:book_id] end end
Even though all the ugly before actions are still there we’ve constrained them to one source file. Our original goal of simplifying the books controller and the routes has been achieved.
Usually when you split out code like this you will get some ideas on how to refactor it further. Don’t worry if you don’t have an epiphany immediately. You can leave the code and think about a great solution in the shower.
Mon, 26 Jan 2015 11:25:51 +0100Authentication, one of the more mundane parts of a Ruby on Rails application, turns out to be pretty diverse. So what are the best practices? First you need to realize that authentication and authorization are different things. Authentication is verifying an identity: who are you? Authorization is enforcing permissions: are you allowed to do this? This means you never name methods and variables in your application auth. Nobody will know what you mean so just type out the entire name. Authn and authz is just weird and only needed when your programming language has length restrictions on names. Choosing a common interface We need a way to fetch the authenticated entity so we need to think of a good name. Commonly used interfaces are methods called user, authenticated, and current_user, sometimes their instance variable counterparts. Which one of these is plain wrong? I would advice against using @user or user, because it carries semantic weight. It suggests that only people can be signed in. When you have a UsersController, which is the record operated on and which is the authenticated? It reminds me of drug (ab)users. Please don't use `me`, it might trigger an existential breakdown in yourself or other programmers. I also wouldn’t recommend using an instance variable in a more complex application, it forces you to use callbacks (e.g. before_action) to set the value. Contact me if you want to hear a long rant about (the misuse of) callback chains. I’ve seen applications use a mix of instance variable (i.e. @current_user) and an accessor method (i.e. current_user). This was possible because the method memoized into the instance variable. This is a side effect of the code and should never be expected! Defining your accessor Methods allow you to abstract fetching of the authenticated model and thus do lazy loading. It also simplifies overloading the behavior on controllers. In the example below we override a method to allow the use of tokens through HTTP Basic Authentication on a controller which is just used by admins. class ApplicationController protected # Cookie based authentication (a SessionsController sets cookie) def authentication_token cookies['authentication_token'] end def authentication_session AuthenticationSession.valid.find_by( token: authentication_token ) end def current_user @current_user ||= authentication_session.try(:user) end end class Admin::AccountsController < ApplicationController protected # HTTP Basic Authentication with x:auth-enti-cati-iont-oken. def authentication_token token, options = ActionController::HttpAuthentication::Token. token_and_options(request) token end end A lot of Rails plugins seem to like using a method called current_user. I’m mostly alright with this name when your authenticated model is named User and it actually returns an instance of that model. If you’re not using a User model might want to consider naming it something more fitting like current_account. In some cases a session is created to represent the authentication person indirectly. Think OAuth or an administrator impersonating another user. In the impersonating case you might want current_user to return the represented user and not the connected client or administrator. You could consider something like this: def current_user if target = authentication_session.target case target when Client, Administrator target.represented_user when User target end end end I personally like the name authenticated because it allows you to have a more flexible authorization system (but that’s a discussion for another day). The authenticated method would return authentication_session.target which could be a User, Consumer, Client, Administrator, or something totally different like a string with a name "John". This is naturally complementary to also defining current_user. For consistency this namin[...]
Fri, 27 Sep 2013 16:47:58 +0200This is the full text of the talk I gave at BubbleConf 2013. Hi there, my name is Thijs van der Vossen. I’m a designer and a developer. Photo by Cuong Bui. Boring I have to warn you before I get started. This is going to be pretty boring. I’m strictly going to talk about business only. Feel free to leave the room in case you were expecting something more exciting. There will be plenty of time to ask questions at the end, so please save anything that might come up for later. Also, you can always reach out to me on Twitter or send me an email. Anyway, let’s get started. Fingertips I run Fingertips, a consulting agency based here in Amsterdam. At Fingertips we build web applications and we make iPhone and iPad apps. Our clients range from small businesses to large multinational corporations. We often do full projects, but we also regularly build complex components, or we work on improving performance, reliability, and overall architecture of existing applications. Every now and then we help startups build and launch the first version of their product, after which we support the transition to an internal development and design team. Recent work we’ve done includes the Wolters Kluwer Annual Report iPad app, an iPhone app for the GaultMillau restaurant guide, the Swiss Car of the Year website, an iPad-optimized web app for Robeco to present their updated corporate identity, and a web-based magazine reader for Schweizer Illustrierte. We’ve helped 37signals improve the reliability and performance of their Highrise iPhone app, we made the backend platform for Zady, we helped build the publishing backend for the NRC Reader, we added some of the more complex features to Freckle Time Tracking, we wrote the functional testing layer for RubyMotion, we added payment integration to Nedap’s Caren, we’re doing Rails work for Viewbook and we made their mobile gallery viewer. How I got started I started out doing web development in the late 90s when I was studying Psychology at the University of Amsterdam. I got hired there as a student assistant on a research project. One of my tasks on this project was to build a web app that helps first-year students evaluate and improve their study skills. Around the same time, I also started working part-time as a developer at a full-service web agency. The people running this agency didn’t do a very good job managing the projects they brought in, and I quickly ended up in the role of lead developer as well as project manager on a big job for an e-commerce startup. This might sound cool, but it really wasn’t much fun at all. I was still a student, so I didn’t have the time to work full-time. I was also still getting paid as a junior programmer. The client sometimes called in the middle of the night. Shortly after the project launched, I decided to quit and to start working freelance. I figured I would make more money, and I would get back control over my working hours. Also, having seen how this company was managed, running my own business suddenly didn’t seem like a big deal anymore. I got my first contract signed in November 1999, sent out my first invoice in January 2000, hired my first employee in May 2002, and got married in 2004. By the way, at this point I’d like to thank my wife for naming the company “Fingertips”. Our son was born in early 2005, we changed from a proprietorship to a limited liability company in 2007, then our daughter was born in the summer of 2008. In 2012 we hired our fourth employee. I’m sorry for rambling on like this, but I wanted to make sure you have an idea where the advice I’m about to give is coming from. The Customer The single most important thing for any business is the customer. Only because your customers are willing to pay for your product or service, will you make money. Without the customer, your business cannot exist. How you find customers depends on the product or service you offer.[...]
Thu, 05 Sep 2013 15:51:56 +0200
There are three major influences on the total runtime of your test suite. Downloading code, installing dependencies, and running the actual suite.
That leaves installing dependencies. They need to be downloaded, possibly compiled, and installed. That takes time.
Most Rails and Ruby projects install all their dependencies using Bundler. This makes it an easy target for optimization. We're definitely not the first to notice this. Both Matias Korhonen and Michał Czyż already proposed a similar solution. WAD is different because it's ready to be added to the project with minimal setup.
You only need to drop the WAD script in the bin/ or script/ directory of your project and swap out Bundler for WAD in your Travis configuration.
You can find detailed setup instructions in the project's README on GitHub.
On every run WAD tries to fetch the bundle from a configured S3 bucket. When the bundle hasn't been cached yet it calls Bundler and creates a tarball of the .bundle directory. After installing the bundle WAD pushes the tarball to S3. On every next run the tarball is downloaded and unpacked.
We get automatic cache invalidation by basing the bundle name on the contents of Gemfile.lock, the Ruby version, and the Ruby platform.
Time saved by using WAD depends on the amount of dependencies and install times of the gems. On an average project it will probably save you around two minutes.
Please give it a try and let us know if you run into any trouble.