Rails 総復習1ヶ月チャレンジ 1日目(Railsチュートリアル編)

やる目的

スクールでポートフォリオ作成期間も含め約8ヶ月間集中して学習してきたつもりでしたが、いざ何社か選考に進み技術面談!となった時にあれ?全く覚えたことが出てこない・・・となり見事に全て撃沈。。。
その為まずは技術面談を突破出来るよう1ヶ月Railsの総復習期間に充てることに決めました!
なおこれでも身にならなかった場合は他職種も視野に入れ就活になる可能性が高いので気合入れていきたいと思います!

進め方

Ruby on Railsチュートリアル(5日間程度)
②スクールカリキュラム復習(基礎編・応用編 12日間程度)
③パーフェクトRails(必要な部分 7日間程度)
④(アプリ作成)→時間に余裕あれば、恐らくなさそう

全部を復習したいところですが、時間も限られているので自分の理解が不十分だなと感じたところを中心にやっていきたいと思います!

その他、夜はTwitterで繋がったWebエンジニアの方の個人開発のお手伝いをさせていただき勉強をさせてもらっていきます!

早速初めていきます!

1日目(Ruby on Rails チュートリアル 1〜6章)

titleにprovideメソッドを使ったビューの作成

#app/views/static_pages/home.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>Home | Ruby on Rails Tutorial Sample App</title>
  </head>

こんな風に各viewページに直描きしていたtitleをprovideを用いるとスッキリ書けます!あとはheadとかtitleはapplication.html.erbにまとめるともっとスッキリしますし、他のviewページでもprovideを用いるだけで使い回せますね!

#app/views/static_pages/home.html.erb
<% provide(:title, "Home") %>
<h1>Sample App</h1>
#app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <%= stylesheet_link_tag    'application', media: 'all',
                               'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag    'application',
                               'data-turbolinks-track': 'reload' %>
  </head>

埋め込みRuby(<%...%>とか<%=...%>という記法)の中でRailsのprovideメソッドを使ってタイトルをページごとに変更します。メソッドの引数に"Home"という文字列と、:titleというラベルを関連付けています。そしてタイトルを表示する部分では<%=...%>の中でRubyのyieldメソッドを呼び出してテンプレートのその部分に実際のタイトルが挿入されます。

カスタムヘルパー

上記provideを用いた方法はそのままだと完璧ではありません。何故かというと<% provide(:title, "...") %>を用いていないviewページがあった場合、title部分が空欄となってしまう為です。その為ヘルパーでページタイトルがない場合は基本タイトルのみ表示されるようにメソッドを定義するようにします。

#app/helpers/application_helper.rb
module ApplicationHelper
  def full_title(page_title = '') 
    base_title = "Ruby on Rails Tutorial Sample App"
    if page_title.empty?
      base_title
    else
      page_title + " | " + base_title
    end
  end
end

full_titleメソッドに引数で空のpage_titleを渡し、view側のprovideでtitleが入っていればpage_titleにtitleが入るようにしています。そしてif文の中でpage_titleが空の場合はbase_title、titleが入っていればpage_titleとbase_titleを合わせたものを表示するようにしています。
なおヘルパーでfull_titleメソッドを定義したのでapp/views/layouts/application.html.erbに記述を追加します。

#app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title><%= full_title(yield(:title)) %> | Ruby on Rails Tutorial Sample App</title>
      :
  </head>

ちなみにlink_to、form_with、label_for、image_tag、select_tagなどはRailsで元々用意されているヘルパーメソッドです。

メールアドレスのフォーマットを検証

メールアドレスの入力値を検証する為にformatというオプションを使います。
正規表現については別でまとめる予定なので今回は割愛します)

#app/models/user.rb
class User < ApplicationRecord
 
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX }
end

定数VALID_EMAIL_REGEXにメールアドレスのパターンを代入し、それをformatで有効であるかチェックしています。

ユーザー属性のパスワードを設定

これが今回一番忘れていた部分です。sorceryとかdiviseでブラックボックス的になってしまうのでよく復習したいと思います。 ただ単にパスワードをデータベースに保存するだけだと外部にデータが盗まれてしまった際に生のパスワードが漏洩してしまいます。その為ハッシュ化したパスワードをデータベースに保存します。
手順としては
1.usersテーブルにpassword_digestカラムを追加(Userモデルでhas_secure_passwordを使えるようにするため)
2.gem 'bcrypt'をGemfileに追加(パスワードをハッシュ化する為)
3.Userモデルにhas_secure_passwordを追加

まず1からやっていきます。

$ bundle exec rails generate migration add_password_digest_to_users password_digest:string

usersテーブルにカラムを追加する際には、末尾にto_usersと付けることによりusersテーブルにカラムを追加するマイグレーションRailsによって自動で作成されます。

#db/migrate/[timestamp]_add_password_digest_to_users.rb
class AddPasswordDigestToUsers < ActiveRecord::Migration[6.0]
  def change
    add_column :users, :password_digest, :string
  end
end
$ bundle exec rails db:migrate

続いてgem 'bcrypt'を追加します

#Gemfile
source 'https://rubygems.org'

gem 'rails',          '6.0.3'
gem 'bcrypt',         '3.1.13' #バージョンは適宜調べて入れる
$ bundle install 

次にUserモデルにhas_secure_passwordを追加します。

#app/models/user.rb

class User < ApplicationRecord
  :
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: true
  has_secure_password
end

has_secure_passwordを設定することにより下記機能が使えるようになります。
・ハッシュ化したパスワードをデータベース内のpassword_digestに保存できる。
・仮想的な属性(Userモデルのオブジェクトからは存在しているように見えるがusersテーブルの属性としては存在していない)のpasswordとpassword_confirmationが使えるようになる。また存在性と値が一致するかどうかのバリデーションも追加される。
・authenticateメソッドが使えるようになる。(引数に文字列を入れるとパスワードと一致するとUserオブジェクトを返し、一致しない場合はfalseを返す)

これでハッシュ化したパスワード設定は出来ていますが、パスワードが空の場合と簡単にパスワードを当てられないようにする為に最小文字数をUserモデル追加します。

class User < ApplicationRecord
  :
  has_secure_password
  validates :password, presence: true, length: { minimum: 8 }
end

今回は以上です!