ror:ユーザーモデリング
14942 ワード
前文を受け継ぐ.
ユーザーモデル
ブランチの作成と切り替え
ユーザーモデルの生成
データベースの移行
モデルの使用
コンソールを開く:
ユーザーの新規保存:
ユーザーの検索:
ユーザー情報の変更:
コードは簡単ですので、コメントを見てください.
ユーザーデータ検証
TDDによる開発
テストコマンドの実行
有効性テスト
存在性の検証
テストは失敗しました.存在検証を追加する必要があります.
同様に、emailの存在性検証を追加します.
長さの検証
このテストは失敗しました.長さ制限を追加します.
フォーマット検証
フォーマット制限の追加:
一意性の検証
一意性の制限を追加するには、次の手順に従います.
索引の追加
移行ファイルを生成するには、次の手順に従います.
一意性制約の移行を追加するには、次の手順に従います.
データベース移行の実行:
セキュリティパスワードの追加
パスワード列の追加
gemの追加
bundleの実行:
コードの追加
テストの変更
パスワード最短長
テストの追加:
パスワードの長さ制限を追加するには、次の手順に従います.
ユーザーの作成
の最後の部分
連結ブランチの削除
Herokuに配備してテストする
リファレンス
《Rails Tutorial 3th》
ユーザーモデル
ブランチの作成と切り替え
git checkout -b modeling-users
ユーザーモデルの生成
rails generate model User name:string email:string
データベースの移行
rails db:migrate
# rails db:rollback( )
モデルの使用
コンソールを開く:
➜ microblog git:(modeling-users) rails c --sandbox #
Running via Spring preloader in process 23202
Loading development environment in sandbox (Rails 5.0.1)
Any modifications you make will be rolled back on exit
ユーザーの新規保存:
2.3.3 :001 > User.new #
=> #
2.3.3 :002 > User.new name:"Joshua", email:"[email protected]" # (Hash , { })
=> #
2.3.3 :003 > user = User.new name:"Joshua", email:"[email protected]" #
=> #
2.3.3 :004 > user.valid? #
=> true
2.3.3 :005 > user.save #
(0.2ms) SAVEPOINT active_record_1
SQL (31.0ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "Joshua"], ["email", "[email protected]"], ["created_at", 2017-01-06 14:55:02 UTC], ["updated_at", 2017-01-06 14:55:02 UTC]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> true # true/false
2.3.3 :006 > user # ( :ID/ / )
=> #
2.3.3 :007 > user.name #
=> "Joshua"
2.3.3 :008 > user.email #
=> "[email protected]"
2.3.3 :009 > user.updated_at #
=> Fri, 06 Jan 2017 14:55:02 UTC +00:00
2.3.3 :010 > user = User.create(name:"Joshuaber", email:"[email protected]") # create new+save
(0.2ms) SAVEPOINT active_record_1
SQL (0.3ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "Joshuaber"], ["email", "[email protected]"], ["created_at", 2017-01-06 14:58:04 UTC], ["updated_at", 2017-01-06 14:58:04 UTC]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> #
2.3.3 :011 > user #
=> #
2.3.3 :012 > user.destroy #
(0.2ms) SAVEPOINT active_record_1
SQL (0.3ms) DELETE FROM "users" WHERE "users"."id" = ? [["id", 2]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> #
2.3.3 :013 > user #
=> #
ユーザーの検索:
2.3.3 :014 > User.find(1) # id=1 ( )
User Load (573.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> #
2.3.3 :015 > User.find(2)
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
ActiveRecord::RecordNotFound: Couldn't find User with 'id'=2
... ...
2.3.3 :016 > user # id=2
=> #
2.3.3 :017 > User.find(2) #
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
ActiveRecord::RecordNotFound: Couldn't find User with 'id'=2
... ...
2.3.3 :018 > User.find_by(email:"[email protected]") # find_by
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "[email protected]"], ["LIMIT", 1]]
=> #
2.3.3 :019 > User.first #
User Load (0.3ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
=> #
2.3.3 :020 > User.last #
User Load (0.3ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT ? [["LIMIT", 1]]
=> #
2.3.3 :021 > User.all #
User Load (0.4ms) SELECT "users".* FROM "users"
=> #<:relation id:="" name:="" email:="" created_at:="" updated_at:="">]>
ユーザー情報の変更:
2.3.3 :022 > user = User.find(1) #
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> #
2.3.3 :023 > user.email = "[email protected]" #
=> "[email protected]"
2.3.3 :024 > user.save #
(0.2ms) SAVEPOINT active_record_1
SQL (0.3ms) UPDATE "users" SET "email" = ?, "updated_at" = ? WHERE "users"."id" = ? [["email", "[email protected]"], ["updated_at", 2017-01-07 03:33:54 UTC], ["id", 1]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> true
2.3.3 :025 > user.email = "[email protected]" #
=> "[email protected]"
2.3.3 :026 > user.reload.email # ( )
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> "[email protected]"
2.3.3 :027 > user #
=> #
2.3.3 :028 > user.created_at #
=> Fri, 06 Jan 2017 14:55:02 UTC +00:00
2.3.3 :029 > user.updated_at #
=> Sat, 07 Jan 2017 03:33:54 UTC +00:00
2.3.3 :030 > user.update_attributes(name:"Joshuaber", email:"[email protected]")
(0.2ms) SAVEPOINT active_record_1
SQL (0.4ms) UPDATE "users" SET "email" = ?, "name" = ?, "updated_at" = ? WHERE "users"."id" = ? [["email", "[email protected]"], ["name", "Joshuaber"], ["updated_at", 2017-01-07 03:37:20 UTC], ["id", 1]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> true
2.3.3 :031 > user.update_attributes(email:"[email protected]") # ( )
(0.1ms) SAVEPOINT active_record_1
SQL (0.2ms) UPDATE "users" SET "email" = ?, "updated_at" = ? WHERE "users"."id" = ? [["email", "[email protected]"], ["updated_at", 2017-01-07 03:38:10 UTC], ["id", 1]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> true
2.3.3 :032 > User.find(1) #
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> #
コードは簡単ですので、コメントを見てください.
ユーザーデータ検証
TDDによる開発
テストコマンドの実行
rails test:models
有効性テスト
# test/models/user_test.rb
... ...
def setup
@user = User.new(name: "Example User", email: "[email protected]")
end
test "should be valid" do
assert @user.valid?
end
... ...
存在性の検証
# test/models/user_test.rb
... ...
test "name should be present" do
@user.name = " "
assert_not @user.valid? #
end
... ...
テストは失敗しました.存在検証を追加する必要があります.
# app/models/user.rb
validates :name, presence: true
同様に、emailの存在性検証を追加します.
長さの検証
# test/models/user_test.rb
... ...
test "name should not be too long" do
@user.name = "a" * 51 # 50
assert_not @user.valid?
end
test "email should not be too long" do
@user.email = "a" * 256
assert_not @user.valid?
end
このテストは失敗しました.長さ制限を追加します.
# app/models/user.rb
validates :name, presence: true, length: { maximum: 50 }
validates :email, presence: true, length: { maximum: 255 }
フォーマット検証
# test/models/user_test.rb
test "email validation should accept valid addresses" do
valid_addresses = %w[[email protected] [email protected] [email protected] [email protected] [email protected]]
valid_addresses.each do |valid_address|
@user.email = valid_address
assert @user.valid?, "#{valid_address.inspect} should be valid"
end
end
test "email validation should reject invalid addresses" do
invalid_addresses = %w[user@example,com user_at_foo.org [email protected]@bar_baz.com foo@bar+baz.com]
invalid_addresses.each do |invalid_address|
@user.email = invalid_address
assert_not @user.valid?, "#{invalid_address.inspect} should be invalid"
end
end
フォーマット制限の追加:
# app/models/user.rb
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i #
validates :email, presence: true, length: { maximum: 255 }, format: { with: VALID_EMAIL_REGEX }
一意性の検証
# test/models/user_test.rb
... ...
test "email addresses should be unique" do
duplicate_user = @user.dup
duplicate_user.email = @user.email.upcase
@user.save
assert_not duplicate_user.valid?
end
一意性の制限を追加するには、次の手順に従います.
# app/models.user.rb
#
before_save { self.email = email.downcase }
... ...
validates :email, presence: true, length: { maximum: 255 }, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
索引の追加
移行ファイルを生成するには、次の手順に従います.
rails generate migration add_index_to_users_email
一意性制約の移行を追加するには、次の手順に従います.
# db/migrate/20170107075525_add_index_to_users_email.rb
def change
add_index :users, :email, unique: true
end
データベース移行の実行:
rails db:migrate
セキュリティパスワードの追加
パスワード列の追加
rails generate migration add_password_digest_to_users password_digest:string
rails db:migrate
gemの追加
# Gemfile
... ...
gem 'bcrypt'
... ...
bundleの実行:
bundle
コードの追加
# app/models/user.rb
... ...
has_secure_password
end
テストの変更
# test/models/user_test.rb
... ...
def setup
@user = User.new(name: "Example User", email: "[email protected]", password: "joshua", password_confirmation: "joshua")
end
... ...
パスワード最短長
テストの追加:
# test/models/user_test.rb
... ...
test "password should have a minimum length" do
@user.password = @user.password_confirmation = "a" * 5 # max_length = 6
assert_not @user.valid?
end
... ...
パスワードの長さ制限を追加するには、次の手順に従います.
# app/models/user.rb
validates :password, length: { minimum: 6 }
ユーザーの作成
2.3.3 :001 > User.all #
User Load (17.5ms) SELECT "users".* FROM "users"
=> #<:relation>
2.3.3 :002 > User.create(name:"Joshua", email:"[email protected]", password:"joshua", password_confirmation:"joshua") #
(0.1ms) begin transaction
User Exists (24.0ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER(?) LIMIT ? [["email", "[email protected]"], ["LIMIT", 1]]
SQL (12.9ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at", "password_digest") VALUES (?, ?, ?, ?, ?) [["name", "Joshua"], ["email", "[email protected]"], ["created_at", 2017-01-08 04:40:15 UTC], ["updated_at", 2017-01-08 04:40:15 UTC], ["password_digest", "$2a$10$vWuRpVTzhdwVHzRlJBBJi.0jVUSuUJvIUnzybK6QQ1t8FQavFoz5i"]]
(123.8ms) commit transaction
=> #
2.3.3 :003 > User.find_by(email:"[email protected]") #
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "[email protected]"], ["LIMIT", 1]]
=> nil
2.3.3 :004 > User.find_by(email:"[email protected]") #
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "[email protected]"], ["LIMIT", 1]]
=> #
2.3.3 :005 > user = User.find_by(email:"[email protected]") #
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "[email protected]"], ["LIMIT", 1]]
=> #
2.3.3 :006 > user.password_ # Tab
user.password_confirmation
... ...
2.3.3 :006 > user.password_digest #
=> "$2a$10$vWuRpVTzhdwVHzRlJBBJi.0jVUSuUJvIUnzybK6QQ1t8FQavFoz5i"
2.3.3 :007 > user.authenticate("wrongpwd") #
=> false
2.3.3 :008 > user.authenticate("joshua") #
=> #
の最後の部分
連結ブランチの削除
git checkout master
git merge modeling-users
git branch -d modeling-user
git branch
Herokuに配備してテストする
git push heroku master
heroku rake db:migrate
heroku run console --sandbox
リファレンス
《Rails Tutorial 3th》