Skip to content

Commit 5ec6ba6

Browse files
committed
Make a basic User model (including secure passwords)
1 parent 04be326 commit 5ec6ba6

File tree

9 files changed

+103
-1
lines changed

9 files changed

+103
-1
lines changed

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
44
ruby "3.4.3"
55

66
gem "rails", "8.0.2"
7+
gem "bcrypt", "3.1.13"
78
gem "cssbundling-rails", "1.4.3"
89
gem "propshaft", "1.2.1"
910
gem "importmap-rails", "2.1.0"

Gemfile.lock

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ GEM
7676
public_suffix (>= 2.0.2, < 7.0)
7777
ansi (1.5.0)
7878
base64 (0.3.0)
79+
bcrypt (3.1.13)
7980
bcrypt_pbkdf (1.1.1)
8081
benchmark (0.4.1)
8182
bigdecimal (3.2.3)
@@ -347,6 +348,7 @@ PLATFORMS
347348
x86_64-linux-musl
348349

349350
DEPENDENCIES
351+
bcrypt (= 3.1.13)
350352
bootsnap (= 1.18.6)
351353
capybara (= 3.40.0)
352354
cssbundling-rails (= 1.4.3)

app/models/user.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class User < ApplicationRecord
2+
before_save { self.email = email.downcase }
3+
validates :name, presence: true, length: { maximum: 50 }
4+
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
5+
validates :email, presence: true, length: { maximum: 255 },
6+
format: { with: VALID_EMAIL_REGEX },
7+
uniqueness: { case_sensitive: false }
8+
has_secure_password
9+
validates :password, presence: true, length: { minimum: 6 }
10+
end
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class CreateUsers < ActiveRecord::Migration[8.0]
2+
def change
3+
create_table :users do |t|
4+
t.string :name
5+
t.string :email
6+
7+
t.timestamps
8+
end
9+
end
10+
end
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class AddIndexToUsersEmail < ActiveRecord::Migration[8.0]
2+
def change
3+
add_index :users, :email, unique: true
4+
end
5+
end
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class AddPasswordDigestToUsers < ActiveRecord::Migration[8.0]
2+
def change
3+
add_column :users, :password_digest, :string
4+
end
5+
end

db/schema.rb

Lines changed: 9 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/fixtures/users.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
2+

test/models/user_test.rb

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
require "test_helper"
2+
3+
class UserTest < ActiveSupport::TestCase
4+
# test "the truth" do
5+
# assert true
6+
# end
7+
def setup
8+
@user = User.new(name: "Example User", email: "[email protected]", password: "foobar", password_confirmation: "foobar")
9+
end
10+
11+
test "should be valid" do
12+
assert @user.valid?
13+
end
14+
test "name should be present" do
15+
@user.name = ""
16+
assert_not @user.valid?
17+
end
18+
test "email should be present" do
19+
@user.email = ""
20+
assert_not @user.valid?
21+
end
22+
test "name should not be too long" do
23+
@user.name = "a" * 51
24+
assert_not @user.valid?
25+
end
26+
test "email should not be too long" do
27+
@user.email = "a" * 244 + "@example.com"
28+
assert_not @user.valid?
29+
end
30+
test "email validation should accept valid addresses" do
31+
32+
33+
valid_addresses.each do |valid_address|
34+
@user.email = valid_address
35+
assert @user.valid?, "#{valid_address.inspect} should be valid"
36+
end
37+
end
38+
test "email validation should reject invalid addresses" do
39+
invalid_addresses = %w[user@example,com user_at_foo.org user.name@example.
40+
foo@bar_baz.com foo@bar+baz.com]
41+
invalid_addresses.each do |invalid_address|
42+
@user.email = invalid_address
43+
assert_not @user.valid?, "#{invalid_address.inspect} should be invalid"
44+
end
45+
end
46+
test "email addresses should be unique" do
47+
duplicate_user = @user.dup
48+
@user.save
49+
assert_not duplicate_user.valid?
50+
end
51+
test "password should be present (nonblank)" do
52+
@user.password = @user.password_confirmation = " " * 6
53+
assert_not @user.valid?
54+
end
55+
test "password should have a minimum length" do
56+
@user.password = @user.password_confirmation = "a" * 5
57+
assert_not @user.valid?
58+
end
59+
end

0 commit comments

Comments
 (0)