見出し画像

中級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を使うことで、画像のアップロードと管理が簡単になるんだね。

🦊 最後に挙動を確認、うん!いい感じ。

お疲れ様でした!

いいなと思ったら応援しよう!