Why I use Safari for Development

Posted over 2 years back at mir.aculo.us - Home

For web developers, there’s an obvious choice of which browser to use for developing web applications. Firefox it is, right? Wrong.

Standards, schmandards

Let’s compare the two browsers, more specifically Safari 4 vs. Firefox 3.5. Both browsers pass the Acid2 test with flying colors, but when it comes to Acid3, Firefox only reaches 93% compliance (up from 71% in Firefox 3.0). Safari? 100%.

Acid3 on Safari 4

That’s a pretty good start for Safari. Basically, if some HTML/CSS works on Safari, the chances are very high it will work on Firefox 2 and higher, and on IE 6 and higher (with minor tweaks).

Development tools

Firefox comes with no development tools, but it’s easy to install Firebug, the de-facto industry standard for HTML inspection, CSS munging and JavaScript debugging. But Firebug has been haunted by bugs lately, and the new 1.4 series is still in beta. Moreover, it feels a bit tacked-on and sometimes just fails to work or becomes unresponsive, or slows things down (hopefully this will be resolved in the 1.4 final, overall Firebug was one of the awesomest things ever for web developers, and I don’t ever want to go back to the days of alerts).

Firebug 1.4 beta network panel

On the plus side, there’s some really great additional plugins like YSlow and Smush.it. I tend to use those independently of the main development cycle, as these tools are more for deployment optimization anyway, so they don’t really play into the development of the web app as such.

Safari 4 Resources Panel

Safari comes with everything you need installed, and the tools themselves are very stable. And they even look nice, which makes debugging less of a drama. I especially like the Profiler, which has features not found in Firebug that come in really handy if you’re doing advanced JavaScript. The tools are very well integrated and are part of the application instead of an add-on, which also means they can access the browser/network data on a deeper level then Firebug can.

Safari Console Autocomplete

The console in Safari has some nifty features, foremost a well-working autocomplete implementation. Firefox has autocomplete too, but doesn’t show you the current option until after you hit <tab>.

The user interface is much more streamlined and cleaned up on Safari as well. The only gripe I have is that I’m not in love with the font the console and debugger on Safari uses (but I’m a font nerd).

JavaScript

And important (for me!) distinction between the two browsers is that Firefox messes with your JavaScript by doing a pre-optimization step on declaration. This means that:

function x(a){
  return 1*2;
}

will be automatically converted into

function x(a){
  return 2;
}

This change is not internal– if you to a x.toString() on the function source code actually has changed. I’m not very much in love with this automatic optimization step– I’d rather see this done by some kind of external tool, like the YUI Compressor, which does some of these microoptimizations. Neither Safari, nor Chrome or IE does that.

Quick, fix that bug!

I’ve done several bug reports to the WebKit project over the years, and all of them where eventually adressed (in big projects like this, it can be expected that non-critical issues might take a while to be resolved). On Firefox, there’s been certain bugs that have a long history of developer hairpulling and nailbiting. Here’s my favourite (Quote: “This bug reveals a problem in Mozilla post-release bug fixing. We have been made to wait 6 years for this bug to be fixed.”).

Note that I’m sure that the people working on the Firefox development team are working very hard (I know some of the awesome people who worked there!), and it’s more of a management issue.

Conclusion

I used Firefox since version 1.0 for my web development, but I’ve switched over to Safari for 99% of my development needs. I only go back to Firefox to make sure it works there and for some of the plugins.

Btw, I know that there are operating systems other than OS X out there. But I’m not using them for development, for several reasons, one of them being that OS X is the only system that allows me to test all major browsers side-by-side by means of virtualization software (I run IE6/7/8 in VMs), and have a Firefox on Linux VM, too. And the iPhone Simulator that comes with XCode runs only the Mac, of course. If you’re serious about front-end web development, there’s pretty much only one OS choice (Let the flamewars begin!).

Presentation:The Internal Design of Force.com’s Multi-Tenant Architecture

Posted over 2 years back at InfoQ Personalized Feed for unregistered user - Register to upgrade!

Craig Weissman, Chief Software Architect at Salesforce.com, presents their multi-tenant architecture, one shared database and one application stack, that has proven to scale well over the years. By Craig Weissman

Double Shot #492

Posted over 2 years back at A Fresh Cup


A bit sad to watch people get all excited over vaporware. We never learn, do we?

FutureRuby!

Posted over 2 years back at Rail Spikes

Jon and I will be at FutureRuby this weekend (actually, I will be there, and Jon will be speaking).

Say “hi” if you see us. I’m flying into Toronto Thursday for FAILcamp.

FutureRuby!

Posted over 2 years back at Rail Spikes

Jon and I will be at FutureRuby this weekend (actually, I will be there, and Jon will be speaking).

Say “hi” if you see us. I’m flying into Toronto Thursday for FAILcamp.

Rails Bundling — Revisited

Posted over 2 years back at Katz Got Your Tongue?

One of the things I spent quite a bit of time on in Merb was trying to get a worker gem bundler that we could be really proud of. Merb had particular problems because of the sheer amount of gems with webbed dependencies, so we hit some limitations of Rubygems quite early. Eventually, we settled on a solution with the following characteristics:

  • A single dependencies file that listed out the required dependencies for the application
  • Only required that the gems you cared about were listed. All dependencies of those gems were resolved automatically
  • A task to go through the dependencies, get the appropriate gems, and install them (merb:gem:install)
  • Gems were installed in a standard rubygems structure inside the application, so normal Rubygems could activate and run them
  • Only the .gem files were stored in source control. These files were expanded out to their full structures on each new machine (via the merb:gem:redeploy task). This allowed us to support native gems without any additional trouble
  • When gems were re-expanded, they took into consideration gems that were already present, meaning that running the deployment task when there were no new gems added to the repo took no time at all (so it could just be added to the normal cap task).

Most importantly, the Merb bundling system relied on a mandatory one-version-per-gem rule that was enforced by keeping the dependencies file in sync with the .gem files in gems/cache. In other words, it would be impossible to have leftover gems or gem activation problems with this system.

There were, however, some flaws. First of all, it was a first pass, before we knew Rubygems all that well. As a result, the code is more clumsy than it needed to be to achieve the task in question. Second, it was coupled to Merb’s dependencies DSL and runtime loader (as well as thor), making it somewhat difficult to port to Rails cleanly. It has since been ported, but it is not really possible to maintain the underlying bundling bits independent of the Rails/Merb parts.

Most importantly, while we did solve the problem of conflicting gems to a reasonable extent, it was still somewhat possible to get into a conflicting state at installation time, even if a possible configuration could be found.

For Rails, we’ve discussed hoisting as much of this stuff as possible into Rubygems itself or a standard library that Rails could interact with, that could also be used by others who wished to bundle gems in with an application. And we have a number of projects at Engine Yard that could benefit from a standard bundler that was not directly coupled with Rails or Merb.

It’s too early to really use it for anything, but Carl and I have made a lot of progress on a gem bundler along these lines. A big part of the reason this is possible is a project I worked on with Tim Carey-Smith a while back (he really did most of the work) called GemResolver. GemResolver takes a set of dependencies and a gem source index and returns back a list of all of the gems, including their dependencies, that need to be installed to satisfy the original list. It does a search of all options, so even if the simple solution would have resulted in the dreaded activation error, it will still be able to find a solution if one exists.

Unlike the Merb bundler, the new bundler does not assume a particular DSL for specifying dependencies, making it suitable for use with Rails, Merb or other projects that wish to have their own DSL for interacting with the bundler. It works as follows:

  • A Manifest object that receives a list of Rubygems sources and dependencies for the application
  • The bundler then fetches the full gem list from each of the sources and resolves the dependencies using GemResolver (which we have merged into the bundler)
  • Once the list is determined, each of the .gem files is retrieved from their sources and stashed
  • Next, each gem is installed, without the need to download their dependencies, since the resolution process has already occurred. This guarantees a single gem per version and a working environment that will not produce activation errors in any circumstance
  • This second step can be run in isolation from the first, so it is possible to expand the gems on remote machines. This means that you can store just the necessary .gem files in version control, and be entirely isolated from network dependencies for deployments
  • Both the fetching and installation steps will not clobber existing .gem files or installed gems, so if there are no new gems, those steps take no time
  • After installation is complete, environment-specific load-path files are created, which means:
  • The bundler will be able to work with or without Rubygems, even though the installed gems are still inside a normal Rubygems structure.

I am providing all this detail for the curious. In the end, as a user, your experience will be quite simple:

  1. List out your dependencies, including what environments those dependencies should be used in
  2. Run rake gem:install
  3. Run your Rails app

In other words, quite similar to the existing gem bundling solution, with fewer warts, and a standard system that you can use outside of Rails if you want to.

<script type="text/javascript"> addthis_url = 'http%3A%2F%2Fyehudakatz.com%2F2009%2F07%2F08%2Frails-bundling-revisited%2F'; addthis_title = 'Rails+Bundling+%26%238212%3B+Revisited'; addthis_pub = ''; </script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12"></script>

Rails Bundling — Revisited

Posted over 2 years back at Katz Got Your Tongue?

One of the things I spent quite a bit of time on in Merb was trying to get a worker gem bundler that we could be really proud of. Merb had particular problems because of the sheer amount of gems with webbed dependencies, so we hit some limitations of Rubygems quite early. Eventually, we settled on a solution with the following characteristics:

  • A single dependencies file that listed out the required dependencies for the application
  • Only required that the gems you cared about were listed. All dependencies of those gems were resolved automatically
  • A task to go through the dependencies, get the appropriate gems, and install them (merb:gem:install)
  • Gems were installed in a standard rubygems structure inside the application, so normal Rubygems could activate and run them
  • Only the .gem files were stored in source control. These files were expanded out to their full structures on each new machine (via the merb:gem:redeploy task). This allowed us to support native gems without any additional trouble
  • When gems were re-expanded, they took into consideration gems that were already present, meaning that running the deployment task when there were no new gems added to the repo took no time at all (so it could just be added to the normal cap task).

Most importantly, the Merb bundling system relied on a mandatory one-version-per-gem rule that was enforced by keeping the dependencies file in sync with the .gem files in gems/cache. In other words, it would be impossible to have leftover gems or gem activation problems with this system.

There were, however, some flaws. First of all, it was a first pass, before we knew Rubygems all that well. As a result, the code is more clumsy than it needed to be to achieve the task in question. Second, it was coupled to Merb’s dependencies DSL and runtime loader (as well as thor), making it somewhat difficult to port to Rails cleanly. It has since been ported, but it is not really possible to maintain the underlying bundling bits independent of the Rails/Merb parts.

Most importantly, while we did solve the problem of conflicting gems to a reasonable extent, it was still somewhat possible to get into a conflicting state at installation time, even if a possible configuration could be found.

For Rails, we’ve discussed hoisting as much of this stuff as possible into Rubygems itself or a standard library that Rails could interact with, that could also be used by others who wished to bundle gems in with an application. And we have a number of projects at Engine Yard that could benefit from a standard bundler that was not directly coupled with Rails or Merb.

It’s too early to really use it for anything, but Carl and I have made a lot of progress on a gem bundler along these lines. A big part of the reason this is possible is a project I worked on with Tim Carey-Smith a while back (he really did most of the work) called GemResolver. GemResolver takes a set of dependencies and a gem source index and returns back a list of all of the gems, including their dependencies, that need to be installed to satisfy the original list. It does a search of all options, so even if the simple solution would have resulted in the dreaded activation error, it will still be able to find a solution if one exists.

Unlike the Merb bundler, the new bundler does not assume a particular DSL for specifying dependencies, making it suitable for use with Rails, Merb or other projects that wish to have their own DSL for interacting with the bundler. It works as follows:

  • A Manifest object that receives a list of Rubygems sources and dependencies for the application
  • The bundler then fetches the full gem list from each of the sources and resolves the dependencies using GemResolver (which we have merged into the bundler)
  • Once the list is determined, each of the .gem files is retrieved from their sources and stashed
  • Next, each gem is installed, without the need to download their dependencies, since the resolution process has already occurred. This guarantees a single gem per version and a working environment that will not produce activation errors in any circumstance
  • This second step can be run in isolation from the first, so it is possible to expand the gems on remote machines. This means that you can store just the necessary .gem files in version control, and be entirely isolated from network dependencies for deployments
  • Both the fetching and installation steps will not clobber existing .gem files or installed gems, so if there are no new gems, those steps take no time
  • After installation is complete, environment-specific load-path files are created, which means:
  • The bundler will be able to work with or without Rubygems, even though the installed gems are still inside a normal Rubygems structure.

I am providing all this detail for the curious. In the end, as a user, your experience will be quite simple:

  1. List out your dependencies, including what environments those dependencies should be used in
  2. Run rake gem:install
  3. Run your Rails app

In other words, quite similar to the existing gem bundling solution, with fewer warts, and a standard system that you can use outside of Rails if you want to.

<script type="text/javascript"> addthis_url = 'http%3A%2F%2Fyehudakatz.com%2F2009%2F07%2F08%2Frails-bundling-revisited%2F'; addthis_title = 'Rails+Bundling+%26%238212%3B+Revisited'; addthis_pub = ''; </script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12"></script>

My Apprenticeship - Thursday, July 8, 2004

Posted over 2 years back at Jake Scruggs

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Thursday 7-8-04

Today Paul and I set up the conference room for next week's class by making sure IntelliJ, FitNesse, and M.S. Visual Studio were installed and current on the mini computers. It's gonna be a full house for the TDD (test driven design) class -- six computers with 2 people at each.

Then Micah gave us a choice: one of us could try to track down a mysterious file on a computer about to be re-formatted and the other was to figure out Word Press and install it. I chose Word Press -- it's a program that can be installed on a server so that blogging (weB LOGging) is quick and easy. We are setting up a blog so we can start the site www.butunclebob.com where individuals can object to Uncle Bob's (Bob Martin, founder of Object Mentor is often referred to as 'Uncle Bob.' I don't know why either) frequent declarations (like: 'Debuggers are bad' or 'Comments should not be used' ) and then Bob can respond. But the servers are Linux based, so I needed to install Linux on an old computer they had lying around. Linux is an operating system( like Windows, or Mac OS) favored by nerds. Long have I wanted to get my hands on this O.S. ' it's in all the great nerd literature like Crytomonicon or, uh' hmm. Maybe something by Coupland? Anyway, the nerds favor this O.S. because, although it's not the most user-friendly of file systems, it is very stable and secure. Linux servers don't crash as often as windows servers but even when they do, it's not too hard to get them back up and running.

So I installed Red Hat Linux, and then I installed it again because I did it wrong the first time. Yargh. After that I downloaded My SQL and PHP. These are programs that Word Press needs to run on a server. What they actually do, I'm not sure, but I'll have to look into that later because, by that time, I had to go.

Wow, first day using linux. These days it's easy to forget that I wasn't alway in love with the *nix based operating systems, but there was a time when I was a windows developer. I remember getting placed on a Rails project and trying to get it up and running on my windows laptop -- I think it took about a week. Eventually I gave up and dual booted Ubuntu. After that I made the switch to OSX.

I love the part where I explain that Linux is more reliable than Windows and what a 'blog' is. Who did I think was reading this? As if me explaining every 20th technical term was going to make this blog any easier to read. Actually I didn't even think of those original posts as a blog -- It was just sort of an extension of the little stories I'd been telling for years on my crappy website.

Also, take note of today's date and keep track of how many days it takes me to install WordPress. At the time their website boasted a "5 minute install." I might have gone a little over that estimate.

smtp_tls 1.0.3

Posted over 2 years back at Segment7

Provides SMTP STARTTLS support for Ruby 1.8.6 (built-in for 1.8.7+). Simply require ‘smtp_tls’ and use the Net::SMTP#enable_starttls method to talk to servers that use STARTTLS.

  require 'net/smtp'
  begin
    require 'smtp_tls'
  rescue LoadError
  end

  smtp = Net::SMTP.new address, port
  smtp.enable_starttls
  smtp.start Socket.gethostname, user, password, authentication do |server|
    server.send_message message, from, to
  end

You can also test your SMTP connection settings using mail_smtp_tls:

  $ date | mail_smtp_tls smtp.example.com submission \
    "your username" "your password" plain \
    from@example.com to@example.com
  Using SMTP_TLS 1.0.3
  -> "220 smtp.example.com ESMTP XXX\r\n"
  <- "EHLO you.example.com\r\n"
  -> "250-smtp.example.com at your service, [192.0.2.1]\r\n"
  -> "250-SIZE 35651584\r\n"
  -> "250-8BITMIME\r\n"
  -> "250-STARTTLS\r\n"
  -> "250-ENHANCEDSTATUSCODES\r\n"
  -> "250 PIPELINING\r\n"
  <- "STARTTLS\r\n"
  -> "220 2.0.0 Ready to start TLS\r\n"
  TLS connection started
  <- "EHLO you.example.com\r\n"
  -> "250-smtp.example.com at your service, [192.0.2.1]\r\n"
  -> "250-SIZE 35651584\r\n"
  -> "250-8BITMIME\r\n"
  -> "250-AUTH LOGIN PLAIN\r\n"
  -> "250-ENHANCEDSTATUSCODES\r\n"
  -> "250 PIPELINING\r\n"
  <- "AUTH PLAIN BASE64_STUFF_HERE\r\n"
  -> "235 2.7.0 Accepted\r\n"
  <- "MAIL FROM:<from@example.com>\r\n"
  -> "250 2.1.0 OK XXX\r\n"
  <- "RCPT TO:<to@example.com>\r\n"
  -> "250 2.1.5 OK XXX\r\n"
  <- "DATA\r\n"
  -> "354  Go ahead XXX\r\n"
  writing message from String
  wrote 91 bytes
  -> "250 2.0.0 OK 1247028988 XXX\r\n"
  <- "QUIT\r\n"
  -> "221 2.0.0 closing connection XXX\r\n"

This will connect to smtp.example.com using the submission port (port 587) with a username and password of “your username” and “your password” and authenticate using plain-text auth (the submission port always uses SSL) then send the current date to to@example.com from from@example.com.

Debug output from the connection will be printed on stderr.

Changes:

  • 1 minor enhancement
    • Added mail_smtp_tls executable to test SMTP connections
  • 2 bug fixes
    • Suppress default DH parameters warning
    • Pass debug output down to child IOs

Presentation:Hooking Stuff Together - Programming the Cloud

Posted over 2 years back at InfoQ Personalized Feed for unregistered user - Register to upgrade!

This talk describes the constraints of connected systems design and presents common design patterns to address some of the challenges developers will face as they spend more time connecting services and components instead of developing new ones. Along the way he asks: Is coupling really so bad? Why is REST popular? Do we need distributed transactions? By Gregor Hohpe

First test release of circular genome browser

Posted over 2 years back at Saaien Tist



Worked a couple of days on pARP, the circular genome browser, and I think it's ready to be tested out by others. Consider this an alpha release: expect a lot of issues. It's easy to create regions with a negative length, for example. Also, I didn't focus yet on user-friendliness or general input files. Ways of interaction are not made clear to new users yet and the input files still need to have fixed names and be stored in a particular folder.

pARP is designed to be a genome browser for features that are linked to other features on a genome (e.g. readpair mappings). Using a circular display, lines can be drawn connecting these features.

pARP always shows the whole genome. You can zoom into selected regions but the rest is still shown albeit squeezed a bit more together. The reason for this is that I want to show the context at all times. Suppose you'd zoom into two regions A and B that are linked by a large number of readpairs. If the part of the genome that is not A or B is not shown any readpair that has only one of its reads in A or B will just not be shown. By showing the whole genome, even squeezed in a few pixels, you can at least see that some reads are linked outside of A and B.



I've put some information on the github wiki page, such as how to interact and what the datafiles should look like.

For a little taste: here's a very brief screencast:
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/4aAuBTNuw1M&amp;hl=en&amp;fs=1&amp;rel=0"><param name="allowFullScreen" value="true"><param name="allowscriptaccess" value="always"><embed src="http://www.youtube.com/v/4aAuBTNuw1M&amp;hl=en&amp;fs=1&amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object>


A lot of things still need to happen:

  • Catch a lot of edge cases
  • Incorporate a library for fast loading of features (i.e. LocusTree, which doesn't exist yet)
  • Make interaction more straightforward: use mouse for panning/zooming for example
  • About 1,472 other things that I currently forget
Also: I'm looking for a new name for pARP. pARP stands for "processing abnormal readpairs" (which what is was meant for originally), but it's actually just a genome browser using a circular representation to show linked features. Suggestions I already got are encircle and SqWheel or Squeal (the last two based on sequence-wheel; Squeal was my own idea, so I like that most at the moment :-) ).

A very, very big thanks goes to Jeremy Ashkenas, the author of ruby-processing. With pARP I have been pushing the boundaries of what that library does, and he has adapted it for my needs as I went. See here for his ruby-processing library.

pARP can be downloaded or cloned from github. Mac, Windows and linux are available there as well.

Rails Envy Podcast – Episode #086: 07/08/2009

Posted over 2 years back at Rails Envy - Home

Episode 86. We bring you the latest news in the Ruby and Rails world. This week features co-host Nathan Bibler, tequila, a singing robot, and a Hoedown. What more could you ask for?

Subscribe via iTunes – iTunes only link.
Download the podcast ~14:00 mins MP3.
Subscribe to feed via RSS by copying the link to your RSS Reader



Runway is a GTD-style action management web application made by geeks for geeks. Created by the folks at Cogent, try a free demo at http://www.runwayapp.com.

Sponsored by New Relic
NewRelic not only provides rails performance monitoring with RPM, but they also produce Rails Lab, a website dedicated to advice on tuning and optimizing Rails apps.

Show Notes

Update: After pushing out the podcast, I received the following Tweet from @thoughtbot:

LOL, see.. thoughtbot’s can sing!

Rails Envy Podcast – Episode #086: 07/08/2009

Posted over 2 years back at Rails Envy - Home

Episode 86. We bring you the latest news in the Ruby and Rails world. This week features co-host Nathan Bibler, tequila, a singing robot, and a Hoedown. What more could you ask for?

Subscribe via iTunes – iTunes only link.
Download the podcast ~14:00 mins MP3.
Subscribe to feed via RSS by copying the link to your RSS Reader



Runway is a GTD-style action management web application made by geeks for geeks. Created by the folks at Cogent, try a free demo at http://www.runwayapp.com.

Sponsored by New Relic
NewRelic not only provides rails performance monitoring with RPM, but they also produce Rails Lab, a website dedicated to advice on tuning and optimizing Rails apps.

Show Notes

Update: After pushing out the podcast, I received the following Tweet from @thoughtbot:

LOL, see.. thoughtbot’s can sing!

Rails Envy Podcast - Episode #086: 07/08/2009

Posted over 2 years back at Rails Envy - Home

Episode 86. We bring you the latest news in the Ruby and Rails world. This week features co-host Nathan Bibler, tequila, a singing robot, and a Hoedown. What more could you ask for?

Subscribe via iTunes - iTunes only link.
Download the podcast ~14:00 mins MP3.
Subscribe to feed via RSS by copying the link to your RSS Reader



Runway is a GTD-style action management web application made by geeks for geeks. Created by the folks at Cogent, try a free demo at http://www.runwayapp.com.


Sponsored by New Relic NewRelic not only provides rails performance monitoring with RPM, but they also produce Rails Lab, a website dedicated to advice on tuning and optimizing Rails apps.

Show Notes


Update: After pushing out the podcast, I received the following Tweet from @thoughtbot:

LOL, see.. thoughtbot's can sing!

sign up, sign in, sign out

Posted over 2 years back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

What is your Ubiquitous Language for authentication?

Common language includes “logging in”, “registering”, “joining up”, “creating an account”, “signing up”, & “signing out”.

Do you interchange these words in your UI? How about in your application code? Tests? Does your whole team use the same language across all layers of the software?

When writing a library like Clearance, I feel the authors should take a stand on language to alleviate the mental burden on designers, developers, & business analysts involved in the project.

The decision is basically arbitrary. No one set of terms is truly better than the other. What’s important is to take the opportunity to standardize all the places this shows up in code.

So we picked “sign up”, “sign in”, & “sign out”, a lingual trinity of authentication.

We liked the symmetry. We liked that there was less of a chance of writing “log in” (sounds like a verb) or “log_in” in certain places and “login” (sounds like a noun) other places.

About a half a year later and we still feel good about the effect:

Tests

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
context "when signed out" do
  setup { sign_out }

  context "on get to new" do
    setup { get :new }
    should_deny_access
  end
end

context "when signed in" do
  setup { sign_in }

  context "on get to new" do
    setup { get :new }
    ...
  end
end

context "when signed in as an admin" do
  setup { sign_in_as Factory(:admin_user) }

  context "on delete to destroy" do
    setup { delete :destroy }
    ...
  end
end

Application code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class UsersController < Clearance::UsersController
  def create
    ...
    sign_in(@user)
  end
end

class ParticipationsController < ApplicationController
  protected
  def ensure_signed_in
    unless signed_in?
      store_location
      flash[:failure] = "Please sign in to participate in this deal."
      redirect_to sign_in_path
    end
  end
end

module NavigationHelper
  def authentication_links
    if signed_in?
      signed_in_links
    else
      signed_out_links
    end
  end

  def signed_out_links
    [link_to("Sign up", sign_up_path),
     link_to("Sign in", sign_in_path)]
  end

  def signed_in_links
    [link_to("My Account", edit_user_path(current_user)),
     link_to("Sign out",   sign_out_path)]
  end
end

UI

For something as common as authentication, familiarity for users breeds comfort. So what do the big boys do?

Basecamp is a little inconsistent, mixing sign in with login:

Apple is pretty as usual:

Google is perfectly consistent. Youtube & Gmail:

Ahh… sweet, sweet consistency.