【Rails学習ノート】ユーザーモデル
4584 ワード
なぜ自分でユーザー検証システムを開発するのか
基本的にすべてのWebアプリケーションには、何らかのログインとユーザー認証システムが必要です.そのため、Webフレームワークには多くの検証システムの実装案があり、Railsも例外ではない.Clearance、Authlogic、Devise、CanCanなど、ユーザー認証および認可システムはたくさんあります(Rails向けではないOpenIDおよびOAuthベースで開発されたシステムもあります).なぜ車輪を繰り返し製造するのか、なぜ既存のソリューションを直接使わずに自分で開発するのかと聞かれるに違いありません.
まず、多くのWebサイトのユーザー検証システムがサードパーティのコードライブラリをカスタマイズし、変更することが実証されています.これは、検証システムを再開発するよりも多くの作業量がかかります.また、既存の案は「ブラックボックス」のようなもので、その中にどんな機能があるのか理解できず、自分で開発すれば実現の過程をよりよく理解することができます.また,Railsの最近の更新により,検証システムの開発が容易になった.最後に、後続の開発でサードパーティのコードライブラリを使用する場合は、自分で開発したので、実装プロセスをよりよく理解し、カスタマイズ機能を容易にすることができます.
「テスト・データベース」の正しいコマンドを作成するには、次の手順に従います.
$ bundle exec rake test:prepare
カラムにインデックスを作成するには、Railsでデータベース移行によって実現できるデータベースモデルを変更する必要があります.
letメソッドRSpecが提供するletメソッドを使用して、テストでローカル変数を簡単に定義できます.letメソッドの構文は少し変に見えますが、変数付与文の役割と同じです.letメソッドのパラメータはSymbolであり,後でブロックに従うことができ,ブロック内のコードの戻り値はSymbolという名前の局所変数に与えられる.すなわち、let(:found_user){User.find_by(email:@user.email)}はfound_という名前を定義するuserの変数でfind_に等しい値byの戻り値.この変数は、このテスト例のいずれかのbeforeまたはitブロックで使用できます.letメソッドを使用して変数を定義する利点の1つは、変数の値を記憶できることです.(memoizeは業界用語で、「memorize」の誤スペルではありません.)上のコードではletのメモ機能でfound_userの値は記憶されるので、Userモデルテストを何回呼び出してもfind_byメソッドは1回しか実行されません.
最終ユーザーモデルは次のとおりです.
テストファイルは次のとおりです.
基本的にすべてのWebアプリケーションには、何らかのログインとユーザー認証システムが必要です.そのため、Webフレームワークには多くの検証システムの実装案があり、Railsも例外ではない.Clearance、Authlogic、Devise、CanCanなど、ユーザー認証および認可システムはたくさんあります(Rails向けではないOpenIDおよびOAuthベースで開発されたシステムもあります).なぜ車輪を繰り返し製造するのか、なぜ既存のソリューションを直接使わずに自分で開発するのかと聞かれるに違いありません.
まず、多くのWebサイトのユーザー検証システムがサードパーティのコードライブラリをカスタマイズし、変更することが実証されています.これは、検証システムを再開発するよりも多くの作業量がかかります.また、既存の案は「ブラックボックス」のようなもので、その中にどんな機能があるのか理解できず、自分で開発すれば実現の過程をよりよく理解することができます.また,Railsの最近の更新により,検証システムの開発が容易になった.最後に、後続の開発でサードパーティのコードライブラリを使用する場合は、自分で開発したので、実装プロセスをよりよく理解し、カスタマイズ機能を容易にすることができます.
「テスト・データベース」の正しいコマンドを作成するには、次の手順に従います.
$ bundle exec rake test:prepare
カラムにインデックスを作成するには、Railsでデータベース移行によって実現できるデータベースモデルを変更する必要があります.
letメソッドRSpecが提供するletメソッドを使用して、テストでローカル変数を簡単に定義できます.letメソッドの構文は少し変に見えますが、変数付与文の役割と同じです.letメソッドのパラメータはSymbolであり,後でブロックに従うことができ,ブロック内のコードの戻り値はSymbolという名前の局所変数に与えられる.すなわち、let(:found_user){User.find_by(email:@user.email)}はfound_という名前を定義するuserの変数でfind_に等しい値byの戻り値.この変数は、このテスト例のいずれかのbeforeまたはitブロックで使用できます.letメソッドを使用して変数を定義する利点の1つは、変数の値を記憶できることです.(memoizeは業界用語で、「memorize」の誤スペルではありません.)上のコードではletのメモ機能でfound_userの値は記憶されるので、Userモデルテストを何回呼び出してもfind_byメソッドは1回しか実行されません.
最終ユーザーモデルは次のとおりです.
class User < ActiveRecord::Base
before_save { self.email = email.downcase }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :name, presence: true, length: { maximum: 50}
validates :email, presence:true,
format: {with: VALID_EMAIL_REGEX},
uniqueness: {case_sensitive: false}
has_secure_password
validates :password, length: {minimum: 6}
end
テストファイルは次のとおりです.
require 'spec_helper'
describe User do
before do
@user = User.new(name: "haha",
email: "[email protected]",
password: "foobar",
password_confirmation: "foobar")
end
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
expect(@user).not_to be_valid
end
end
end
describe "when email format is valid" do
it "should be valid" do
addresses = %w[[email protected] [email protected] [email protected] [email protected]]
addresses.each do |valid_address|
@user.email = valid_address
expect(@user).to 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 password is not present" do
before do
@user = User.new(name: "Example User", email: "[email protected]",
password: " ", password_confirmation: " ")
end
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 "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 eq found_user.authenticate(@user.password) }
end
describe "with invalid password" do
let(:user_for_invalid_password) { found_user.authenticate("invalid") }
it { should_not eq user_for_invalid_password }
specify { expect(user_for_invalid_password).to be_false }
end
end
end