つまづきポイントだけ解説
DB Browser for SQLiteのダウンロード
2.2で、このコマンドを似たような状況で実行したことを思い出してみてください。初めてdb:migrateが実行されると、db/development.sqlite3という名前のファイルが生成されます。これはSQLite6 データベースの実体です。development.sqlite3ファイルを開くためのDB Browser for SQLiteという素晴らしいツールを使うと、データベースの構造を見ることができます。クラウドIDEを使っている場合は、まずファイルを手元にダウンロードしておく必要があります(図 6.5)。
個人的にここでうんうん、それで?という感じだったので書いてみました。
この情報を見るにはあらかじめDB Browser for SQLiteをダウンロードする必要があります。
ここから↓
https://sqlitebrowser.org/dl/
Windows,Macなどがあるのでそれぞれ選択してください。
私は一番上のStandard installerをダウンロードしました。
ダウンロードが成功したらショートカットなどが作成されるのでそれを開いて
tutorial図6.5に沿ってダウンロードしたdevelopment.sqliteのファイルをドラッグアンドドロップします
とすることでデータベースを表示することが出来ます。
演習 一部
u.errors.messagesを実行すると、ハッシュ形式でエラーが取得できることを確認してください。emailに関するエラー情報だけを取得したい場合、どうやって取得すれば良いでしょうか?
u.errors.full_messages_for(:email)
=> ["Email can't be blank"]
_for(:属性)とすることで特定のエラーメッセージを受け取れます。
こちらでもいけます
u.errors.messages[:email]
=> ["can't be blank"]
名前とメールアドレスは有効でも、パスワードが短すぎるとuserオブジェクトが有効にならないことを確認してみましょう。
user = User.create(name: "Example User", email: "user@example.com")
=> #<User:0x00007f080e11e438 id: nil, name: "Example User", email: "user@example.com", created_at: nil, updated_at: nil, password_digest: nil>
user.password_digest = "aaa"
=> "aaa"
user.valid?
User Exists? (0.1ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "user@example.com"], ["LIMIT", 1]]
=> false
user.errors.messages
=> {:password=>["can't be blank", "is too short (minimum is 6 characters)"]}
上で失敗した時、どんなエラーメッセージになるでしょうか?確認してみましょう。
user.errors.messages
=> {:password=>["can't be blank", "is too short (minimum is 6 characters)"]}
最低6文字以上にしましょうというエラーが発生
bcryptのようなパスワードのハッシュ化に適したアルゴリズムを使っている場合であっても、最小文字数は8文字以上が推奨されています。パスワードの最小文字数を8文字以上にできないか、挑戦してみましょう。(ヒント:最小文字数を変更すると、テストも落ちます。テストも合わせて修正してみましょう)
app/models/user.rb
class User < ApplicationRecord
before_save { self.email = email.downcase }
validates:name, presence: true, length: { maximum:50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
validates :email, presence: true, length: {maximum:255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: true
has_secure_password
#パスワードの文字数を最低8文字に変更
validates :password, presence: true, length: { minimum: 8 }
end
ついでuser_test.rbも変更
require "test_helper"
class UserTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
def setup
@user = User.new(name: "Example User", email: "user@example.com",
#password_confirmationの値を最低8文字にしたので"foobar"のままだと
validateに引っかかる。ここでは適当に8文字以上になるように設定
password: "foobarrr", password_confirmation: "foobarrr")
end
(省略)
.
.
.
test "password should be present (nonblank)" do
@user.password = @user.password_confirmation = " " * 8
assert_not @user.valid?
end
test "password should have a minimum length" do
@user.password = @user.password_confirmation = "a" * 7
assert_not @user.valid?
end
end
※この章で8文字以上の設定のままにすると次の6.3.4の設定でエラーが出てしまう可能性があります。
↓
$ rails console
>> User.create(name: "Michael Hartl", email: "michael@example.com",
?> password: "foobar", password_confirmation: "foobar")
=> #<User id: 1, name: "Michael Hartl", email: "michael@example.com",
created_at: "2022-03-11 03:15:38", updated_at: "2022-03-11 03:15:38",
password_digest: [FILTERED]>
password: "foobar" と password_confirmation: "foobar"が6文字なので、validateに引っかかってしまう。
なので、演習前の状態に戻すか、8文字以上のパスワードを設定した場合は、そのままそれを使用してください。
userオブジェクトを消去するためにコンソールを一度再起動し、本節で作ったuserオブジェクトを検索してみてください。
User.first
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
=>
#<User:0x00007fbcc5c7afb8
id: 1,
name: "Michael Hartl",
email: "michael@example.com",
created_at: Mon, 11 Sep 2023 07:52:30.250238000 UTC +00:00,
updated_at: Mon, 11 Sep 2023 07:52:30.250238000 UTC +00:00,
password_digest: "[FILTERED]">
オブジェクトを検索できたら、名前を別の文字列に置き換え、saveメソッドで更新してみてください。うまくいきませんね...、なぜうまくいかなかったのでしょうか?
user.name = "ryohei"
=> "ryohei"
irb(main):011:0> user.save
TRANSACTION (0.1ms) begin transaction
User Exists? (0.1ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? AND "users"."id" != ? LIMIT ? [["email", "michael@example.com"], ["id", 1], ["LIMIT", 1]]
TRANSACTION (0.0ms) rollback transaction
=> false
user.errors.messages
=> {:password=>["can't be blank", "is too short (minimum is 8 characters)"]}
今度は6.1.5で紹介したテクニックを使って、userの名前を更新してみてください。
#特定の属性のみの更新はattribueを使用するんでしたよね
user.update_attribute(:name, "Ryohei")
TRANSACTION (0.1ms) begin transaction
User Update (0.3ms) UPDATE "users" SET "name" = ?, "updated_at" = ? WHERE "users"."id" = ? [["name", "Ryohei"], ["updated_at", "2023-09-11 08:18:39.867071"], ["id", 1]]
TRANSACTION (26.0ms) commit transaction
=> true
user.name
=> "Ryohei"
User.first
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
=>
#<User:0x00007fbcbf359610
id: 1,
name: "Ryohei",
email: "michael@example.com",
created_at: Mon, 11 Sep 2023 07:52:30.250238000 UTC +00:00,
updated_at: Mon, 11 Sep 2023 08:18:39.867071000 UTC +00:00,
password_digest: "[FILTERED]">