notionの各記事につけることのできる絵文字のように、各ユーザーのnickname
にランダムに絵文字を付与させたいと思います。現在nickname
カラムはstring
型で、null
制約がかかっています。
ランダムにデータを取得する方法について調べてみました。shuffle
やrand
などのメソッドがあったのですが、今回は配列の要素1つをランダムに取得したいので sample
メソッドを使っていこうと思います。
まず最初にUserモデルにユーザーを新規作成する前にset_nicknameメソッドを実行するように設定して行きます。
class User < ApplicationRecord
before_create :set_nickname
privete
def set_nickname
while self.nickname.blank? || User.find_by(nickname: self.nickname).present? do
self.nickname = ['🐴', '🐣', '🦕', '🐡'].sample
end
end
end
これでフォームにnickname
以外を入力せずに保存しようとすると、nickname
が空白で登録できないというバリデーションエラーが発生します。
一旦binding.pry
でデバックして調べてみることにしました。
users_controller.rb
def create
@user = User.new(user_params)
if @user.save
redirect_to login_path, success: t('.success')
else
binding.pry # 失敗する原因を究明するためのbinding.pry
flash.now[:danger] = t('.fail')
render :new
end
end
Started POST "/users" for ::1 at 2021-06-09 14:55:21 +0900
Processing by UsersController#create as HTML
Parameters: {"authenticity_token"=>"[FILTERED]", "user"=>{"nickname"=>"", "name"=>"hanako", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"register"}
TRANSACTION (1.0ms) BEGIN
↳ app/controllers/users_controller.rb:19:in `create'
User Exists? (1.0ms) SELECT 1 AS one FROM `users` WHERE `users`.`name` = 'hanako' LIMIT 1
↳ app/controllers/users_controller.rb:19:in `create'
TRANSACTION (0.8ms) ROLLBACK
↳ app/controllers/users_controller.rb:19:in `create'
From: /Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/app/controllers/users_controller.rb:23 UsersController#create:
17: def create
18: @user = User.new(user_params)
19: if @user.save
20: redirect_to login_path, success: t('.success')
21: else
22: binding.pry
=> 23: flash.now[:danger] = t('.fail')
24: render :new
25: end
26: end
[1] pry(#<UsersController>)> @user
=> #<User:0x00007ffb1d5bae08
id: nil,
nickname: "",
name: "hanako",
crypted_password: "$2a$10$Uv6mDNXav5Dq/wY4.2sZNuL4shZe0Z1FIB9URPkjbzb8g3/QBC9f6",
salt: "y1rNQVe6MQ2Qn7428RP6",
created_at: nil,
updated_at: nil>
想像通り、@userのnicknameカラムが空欄でした。
arrayに配列で並べた絵文字を数個入れました。そして@user
のnickname
にsample
メソッド(配列からランダムに1つデータを取り出してくれる)を使ってデータを入れました。それからsave
をしてみると、保存することができました。実際に新規登録できているか確認するとできているのがわかりました。
[2] pry(#<UsersController>)> array = ['🐴', '🐣', '🦕', '🐡']
=> ["🐴", "🐣", "🦕", "🐡"]
[3] pry(#<UsersController>)> @user.nickname = array.sample
=> "🦕"
[4] pry(#<UsersController>)> @user.save
TRANSACTION (19.2ms) BEGIN
↳ (pry):6:in `create'
User Exists? (5.9ms) SELECT 1 AS one FROM `users` WHERE `users`.`name` = 'hanako' LIMIT 1
↳ (pry):6:in `create'
User Load (47.0ms) SELECT `users`.* FROM `users` WHERE `users`.`nickname` = '🦕' LIMIT 1
↳ app/models/user.rb:73:in `set_nickname'
User Create (59.1ms) INSERT INTO `users` (`nickname`, `name`, `crypted_password`, `salt`, `created_at`, `updated_at`) VALUES ('🦕', 'hanako', '$2a$10$u8nSRJDeHaHzIYAMNr5Rvemla4NvsbS.jF598W2K/1LRC5D1tB3ZS', 'MpnA1wV-d4VVsjTRH_Lr', '2021-06-09 05:57:20.850310', '2021-06-09 05:57:20.850310')
↳ (pry):6:in `create'
TRANSACTION (43.5ms) COMMIT
↳ (pry):6:in `create'
=> true
[5] pry(#<UsersController>)> User.last
User Load (13.7ms) SELECT `users`.* FROM `users` ORDER BY `users`.`id` DESC LIMIT 1
↳ (pry):7:in `create'
=> #<User:0x00007ffb1f984050
id: 12,
nickname: "🦕",
name: "hanako",
crypted_password: "$2a$10$u8nSRJDeHaHzIYAMNr5Rvemla4NvsbS.jF598W2K/1LRC5D1tB3ZS",
salt: "MpnA1wV-d4VVsjTRH_Lr",
created_at: Wed, 09 Jun 2021 14:57:20.850310000 JST +09:00,
updated_at: Wed, 09 Jun 2021 14:57:20.850310000 JST +09:00>
うーん、コンソールでならうまくできるのに、、、。と思ったのでusersコントローラにメソッドを移してみることにしました。
def create
@user = User.new(user_params)
@user.nickname = ['🐴', '🐣', '🦕', '🐡'].sample
if @user.save
redirect_to login_path, success: t('.success')
else
flash.now[:danger] = t('.fail')
render :new
end
end