中級DAY24ユーザのプロフィールページを作ろう②
😺 プロフィールコントローラーでアバターの保存をするように設定にゃ
00.プロフィール内容表示
ぼっち演算子の説明・書き方
😺 こんにちは、きつねさん!今日はプロフィール情報をどうやって表示するかについて勉強しましょうにゃ。
🦊 はい、お願いします!今は適当な情報しか表示していなくて、
実際に保存された正しい情報を表示したいと思っています。
😺 いいですにゃ!まず、display_name メソッドを使って、
ユーザーの表示名を決める方法を説明するにゃ。
これで、プロフィールのニックネームがあればそれを使い、
なければメールアドレスの先頭部分を表示するようにするにゃ
🦊 なるほど、それが display_name メソッドですね。
もしプロフィールがない場合や、ニックネームがない場合でも、
メールアドレスの先頭を使うわけですね
😺 その通りにゃ!次に、プロフィールが存在しない場合のエラーを防ぐために、ボッチ演算子(&.)を使う方法を教えるにゃ。
これを使うと、profile が nil のときにエラーが起こらず、nil を返すことができるにゃ。
例えば、"profile&.nickname" のように書けば、プロフィールが存在する場合にのみニックネームを取得することができるにゃ。
def display_name
#ユーザーの表示名を取得します。
profile&.nickname || self.email.split('@').first
end
def birthday
#ユーザーの誕生日を取得します。
profile&.birthday
end
def gender
#ユーザーの性別を取得します。
profile&.gender
end
🦊 わかりました。
表示するには show.html.haml ファイルに書くんですね?
😺 そうにゃ!以下のコードを使って、
表示名、誕生日、性別を表示するにゃ。
#{current_user.display_name}(#{current_user.birthday}・#{current_user.gender})
🦊 これで、ユーザーのプロフィールが正しく表示されるんですね。
他に気をつけることはありますか?
😺 あと、プロフィールの紹介も表示するために、
次のように書くと良いにゃ。
= current_user.profile&.introduction
🦊 なるほど
01.年齢の表示
ユーザーの年齢計算
😺 では続きをやっていくにゃ〜
🦊 年齢の表示だね、誕生日から計算できそう
😺 その考えで合ってるにゃ!年齢を計算するためのメソッドですにゃ
def age
return '不明' unless birthday.present?
years = Time.zone.now.year - birthday.year
days = Time.zone.now.yday - birthday.yday
if days < 0
"#{years - 1}歳"
else
"#{years}歳"
end
end
🦊 復習にもなりそうだ。内容を細かくみていこう
birthday.present?:
バースデーが存在しない場合は '不明' と表示します。
Time.zone.now.year - birthday.year:
現在の年からバースデーの年を引いて、年齢の大まかな計算をします。
Time.zone.now.yday - birthday.yday:
現在の日付とバースデーの日付から、何日経過しているかを計算します。
if days < 0:
現在の日付がバースデーよりも前の場合、年齢を1年減らします。
"#{years - 1}歳":
年齢を1歳減らして表示します。
"#{years}歳":
現在の年齢を表示します。
😺 次に、delegate を使ってプロフィールのメソッドを簡単に使えるようにする方法も説明するにゃ。
delegate :birthday, :age, :gender, to: :profile, allow_nil: true
🦊 ああ〜もう頭がいっぱいだ
profile オブジェクトから birthday, age, gender メソッドを呼び出せるようにします。
allow_nil: true を設定して、profile が nil の場合でもエラーが発生しないようにします。
🦊 このdelegateって、どんなメソッドなの?
😺 delegate メソッドはRails が提供する便利な機能の一つにゃ。
使うことでコードがシンプルになり、ついでに説明するとallow_nil: true を設定することで nil 値に対処できるようになっているにゃ。
もし他のオブジェクト、例えばprofileメソッドを使う場合下記のような長いコードを書く事になってしまうにゃ。長くてだるいにゃ?
def birthday
profile.birthday
end
def age
profile.age
end
def gender
profile.gender
end
😺 最後に、年齢と性別を表示する方法を確認してみましょうにゃ。
#{current_user.display_name}(#{current_user.age}・#{current_user.gender})
🦊 これで、表示名と一緒に年齢と性別も表示できるんですね。
ふう・・・
😺 これらのコードはネットで調べればテンプレートがあるから覚えなくても こんなことができるって知ってるだけでいいにゃ 安心するにゃ
02.性別の日本語化
多言語化の対応方法とセレクトボックスの設定
😺 性別などの表示を英語から日本語に変更するにゃ
🐹 config/locales/ja.yml ファイルを作成し、
日本語用の翻訳を設定します。
ja:
enums:
gender:
male: "男性"
female: "女性"
other: "その他"
😺 i18n を使って表示するにゃ tメソッドを用いて翻訳を適用にゃ
編集する場所はprofile.showにゃよ。
#これにより、英語の male が「男性」に翻訳されます。
#{current_user.display_name}(#{current_user.age}・#{I18n.t("enum.genders.#{current_user.gender}")})
🐹 ねこ先生、profile.editページにある
セレクトボックスの設定もしたいです!
😺 英語で表示される性別選択肢を日本語にしたいんだにゃ。了解にゃ
# ビューでのセレクトボックス
= f.select :gender, Profile.genders.map { |k, v| [ I18n.t("enum.genders.#{k}"), k ] }, {}, { class: 'text' }
map メソッド: ハッシュを配列に変換し、ラベルとバリューを設定。
例:
Profile.genders.map { |key, value| [t("enums.gender.#{key}"), key] }
🐹 多言語対応と日本語表示の設定が完了ってことですね。
😺 ちょっと難しかったりするけど、config/locales フォルダ内にあるYAMLファイルを使うんだな、I18n.t メソッドを使うんだな、などと、実装までの流れをなんとなく覚えていれば、怖くないにゃ〜
03.画像アップロード ー ActiveStorage
😺 ユーザーアイコンの画像を、好きな画像に変更できるようにするにゃ。
Active Storageのセットアップ
😺 早速、コマンドを実行するにゃ
rails active_storage:install
🦊 でたな!魔法の呪文
🐹 これにより、Active Storage用のマイグレーションファイルが作成されます。
😺 さくっと画像データを保存するためのテーブルが作成するにゃ。
rails db:migrate
モデルの設定
😺 プロフィールモデルにアバターを追加するにゃ
🦊 あいあいさ
class Profile < ApplicationRecord
has_one_attached :avatar
end
🐹 これにより、Profileモデルにavatarという名前の画像を関連付けることができます。
フォームの作成
😺 画像アップロード用のフォームを作成するにゃ
🦊 あいあいさ、プロフィールのエディットページにコードを追加するよ
%div
= f.label :avatar, 'アバター'
%div
= f.file_field :avatar
コントローラーの設定
😺 プロフィールコントローラーでアバターの保存をするように設定にゃ
def avatar_image
if profile&.avatar&.attached?
profile.avatar
else
'default-avatar.png'
end
end
🦊 いい感じだね
画像の表示
😺 ユーザー、プロフィールなどの情報がnillだとエラーになるから、 if…else構文で作成するにゃ
🦊 コードが長いなあ〜しかもこれってユーザーアイコンを表示しているすべてに変更が 必要だ。 そうだ!アクション作って短くしちゃお
🐹 いいぞ!やっちゃえ!
def avatar_image
if profile&.avatar&.attached?
profile.avatar
else
'default-avatar.png'
end
end
🦊 よしこれでavatar_imageを入力すればユーザー画像を表示できるようになった。
= image_tag current_user.avatar_image
😺 うむ、問題なく動いている様子にゃ。current_user の部分はページによって取得できる 条件が違うから修正しないといけないのが注意にゃ。
きつねさん、ヘルパーメソッドを使いこなしてきたにゃ。
🐹 article/show.htmlの場合は、@article.userでユーザー取得になるんだね。
😺 ArticleモデルがUserモデルと関連付けられているからだにゃ
class Article < ApplicationRecord
belongs_to :user
end
😺 この記述があるはずにゃ
🐹 なるほど
🦊 それにしても、Active Storageを使うことで、画像のアップロードと管理が簡単になるんだね。
🦊 最後に挙動を確認、うん!いい感じ。