Permalink
Browse files

Make a basic User model (including secure passwords)

  • Loading branch information...
1 parent 96572a4 commit fe39e915380c5a933204689cd8390cd6fa60b88d @jholton committed Feb 26, 2013
View
@@ -2,12 +2,17 @@ source 'https://rubygems.org'
gem 'rails', '3.2.12'
gem 'bootstrap-sass', '2.1'
+gem 'bcrypt-ruby', '3.0.1'
group :development, :test do
gem 'sqlite3', '1.3.5'
gem 'rspec-rails', '2.11.0'
end
+group :development do
+ gem 'annotate', '2.5.0'
+end
+
group :assets do
gem 'sass-rails', '3.2.5'
gem 'coffee-rails', '3.2.2'
View
@@ -28,7 +28,10 @@ GEM
activesupport (3.2.12)
i18n (~> 0.6)
multi_json (~> 1.0)
+ annotate (2.5.0)
+ rake
arel (3.0.2)
+ bcrypt-ruby (3.0.1)
bootstrap-sass (2.1.0.0)
builder (3.0.4)
capybara (1.1.2)
@@ -140,6 +143,8 @@ PLATFORMS
ruby
DEPENDENCIES
+ annotate (= 2.5.0)
+ bcrypt-ruby (= 3.0.1)
bootstrap-sass (= 2.1)
capybara (= 1.1.2)
coffee-rails (= 3.2.2)
View
@@ -0,0 +1,29 @@
+# == Schema Information
+#
+# Table name: users
+#
+# id :integer not null, primary key
+# name :string(255)
+# email :string(255)
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
+class User < ActiveRecord::Base
+ attr_accessible :email, :name, :password, :password_confirmation
+
+ has_secure_password
+
+ validates :name, presence: true, length: { maximum: 50 }
+
+ VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
+ validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
+ uniqueness: { case_sensitive: false }
+ validates :password, presence: true, length: { minimum: 6 }
+ validates :password_confirmation, presence: true
+
+ before_save { |user| user.email = email.downcase }
+
+ # scopes
+
+end
View
@@ -1,5 +1,4 @@
SampleApp::Application.routes.draw do
- get "users/new"
root to: 'static_pages#home'
match '/signup', to: 'users#new'
@@ -0,0 +1,11 @@
+class CreateUsers < ActiveRecord::Migration
+ def change
+ create_table :users do |t|
+ t.string :name
+ t.string :email
+
+ t.timestamps
+ end
+ end
+
+end
@@ -0,0 +1,5 @@
+class AddIndexToUsersEmail < ActiveRecord::Migration
+ def change
+ add_index :users, :email, unique: true
+ end
+end
@@ -0,0 +1,5 @@
+class AddPasswordDigestToUsers < ActiveRecord::Migration
+ def change
+ add_column :users, :password_digest, :string
+ end
+end
View
@@ -11,6 +11,16 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 0) do
+ActiveRecord::Schema.define(:version => 20130226141524) do
+
+ create_table "users", :force => true do |t|
+ t.string "name"
+ t.string "email"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ t.string "password_digest"
+ end
+
+ add_index "users", ["email"], :name => "index_users_on_email", :unique => true
end
View
@@ -0,0 +1,124 @@
+# == Schema Information
+#
+# Table name: users
+#
+# id :integer not null, primary key
+# name :string(255)
+# email :string(255)
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
+require 'spec_helper'
+
+describe User do
+ before { @user = User.new(name: "Example User", email: "user@example.com",
+ password: "foobar", password_confirmation: "foobar") }
+ subject { @user }
+
+ it { should respond_to(:name) }
+ it { should respond_to(:email) }
+ it { should respond_to(:password_digest) }
+ it { should respond_to(:password) }
+ it { should respond_to(:password_confirmation) }
+ it { should respond_to(:authenticate) }
+
+
+ it { should be_valid }
+
+ describe "when name is not present" do
+ before { @user.name = " " }
+ it { should_not be_valid }
+ end
+
+ describe "when email is not present" do
+ before { @user.email = " " }
+ it { should_not be_valid }
+ end
+
+ describe "when name is too long" do
+ before { @user.name = "a" * 51 }
+ it { should_not be_valid }
+ end
+
+ describe "when email format is invalid" do
+ it "should be invalid" do
+ addresses = %w[user@foo,com user_at_foo.org example.user@foo.
+ foo@bar_baz.com foo@bar+baz.com]
+ addresses.each do |invalid_address|
+ @user.email = invalid_address
+ @user.should_not be_valid
+ end
+
+ end
+ end
+
+ describe "when email format is valid" do
+ it "should be valid" do
+ addresses = %w[user@foo.COM A_US-ER@f.b.org frst.lst@foo.jp a+b@baz.cn]
+ addresses.each do |valid_address|
+ @user.email = valid_address
+ @user.should be_valid
+ end
+
+ end
+ end
+
+ describe "when email address is already taken" do
+ before do
+ user_with_same_email = @user.dup
+ user_with_same_email.save
+ end
+
+ it { should_not be_valid }
+ end
+
+ describe "when email address is already taken" do
+ before do
+ user_with_same_email = @user.dup
+ user_with_same_email.email = @user.email.upcase
+ user_with_same_email.save
+ end
+
+ it { should_not be_valid }
+ end
+
+ describe "when password is not present" do
+ before { @user.password = @user.password_confirmation = " " }
+ it { should_not be_valid }
+ end
+
+ describe "when password doesn't match confirmation" do
+ before { @user.password_confirmation = "mismatch" }
+ it { should_not be_valid }
+ end
+
+ describe "when password confirmation is nil" do
+ before { @user.password_confirmation = nil }
+ it { should_not be_valid }
+ end
+
+ describe "with a password that's too short" do
+ before { @user.password = @user.password_confirmation = "a" * 5 }
+ it { should be_invalid }
+ end
+
+
+ describe "return value of authenticate method" do
+ before { @user.save }
+ let(:found_user) { User.find_by_email(@user.email) }
+
+ describe "with valid password" do
+ it { should == found_user.authenticate(@user.password) }
+ end
+
+ describe "with invalid password" do
+ let(:user_for_invalid_password) { found_user.authenticate("invalid") }
+
+ it { should_not == user_for_invalid_password }
+ specify { user_for_invalid_password.should be_false }
+ end
+ end
+
+
+end
@@ -1,8 +1 @@
-def full_title(page_title)
- base_title = "Ruby on Rails Tutorial Sample App"
- if page_title.empty?
- base_title
- else
- "#{base_title} | #{page_title}"
- end
-end
+include ApplicationHelper

0 comments on commit fe39e91

Please sign in to comment.