0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】Ruby on Rails Tutorial 7章を読み終えて

Posted at

はじめに

こんにちは。アメリカで独学でエンジニアを目指している者です。
現在、Ruby on Rails Tutorialを使ってRailsを勉強しており、学んだことを忘れないように振り返りの記事を書いてみました。

開発環境
OS: Window11
Gemfile: Ruby on Rails Tutorialに書いてあるバージョンを使用
その他 : Doceker + vscodeを用いて開発

ユーザー登録

前回はユーザーの名前やメールアドレスについてのバリデーションを学習しました。今回はそれらを活用してサインアップページを作成し、テストを行うところまでがメインの内容です。

ユーザーを表示する

まずは、Webサイトのレイアウトにデバッグ情報を表示させました。Railsは裏側で動いている処理が多く見えづらいので、デバッグ情報を明示的に表示し、理解を深めるのが狙いだと思われます。以下のように、app/views/layouts/application.html.erbにデバッグ用のコードを追加しました。

application.html.erb
 <!DOCTYPEhtml>
<html>
  .
  .
  .
  <body>
    <%= render 'layouts/header' %>
    <div class="container">
      <%= yield %>
      <%= render 'layouts/footer' %>
      <%= debug(params) if Rails.env.development? %> <!--追加-->
    </div>
  </body>
</html>

Rails.env.development? は、Railsが開発環境(development)のときのみtrueとなります。Railsにはこのほかにも testproduction(本番環境) が用意されています。
ここで引数に渡している params は、HTTPリクエストから受け取ったパラメータを扱うための変数です。詳しい仕様は今後改めて学ぶ予定です。

続いて、routes.rb において users/:id のルーティングが有効になっていなかったので、以下のコードを追記しました。

routes.rb
Rails.application.routes.draw do
  root "static_pages#home"
  get "/help",
  to: "static_pages#help"
  get "/about", to: "static_pages#about"
  get "/contact", to: "static_pages#contact"
  get "/signup", to: "users#new"
  resources :users # 追加
end

resources :users を追加することで、RESTfulなUsersリソースで必要となるアクション(index, show, new, create, edit, update, destroy)にアクセスできるようになります。
RESTfulについては本格的に理解しようとするとややこしいですが、ひとまずは「これでユーザー関連の基本的なルーティングが一括で設定される」と理解しておけばOKです。

debugger

ここでトラブルが発生しました。debugger メソッドを使おうとするとエラーが出てしまい、実行できなかったのです。
実は、$ rails console とGemfile内の

Gemfile
group :development, :test do
  gem "debug", "1.7.1", platforms: %i[ mri mingw x64_mingw ] 
end

が干渉しており、毎回この行をコメントアウトしないと $ rails console が使用できませんでした。しかし、debugger を使うには上記のGemを有効化しておく必要があるため、コメントアウトするわけにもいかず、ChatGPTを使って解決策を模索しました。

エラーメッセージの一部に

/usr/local/rvm/rubies/ruby-3.2.3/lib/ruby/gems/3.2.0/gems/debug-1.7.1/lib/debug/console.rb:25:in reset': missing keyword: :encoding (ArgumentError)

とあり、console.rbの中に

# reline 0.2.7 or later is required.
  raise LoadError if Reline::VERSION < '0.2.7'

という記述がありました。そこで以下のコマンドで現在のrelineバージョンを確認してみました。

gem list reline
# 実行結果

WARN: Unresolved or ambiguous specs during Gem::Specification.reset:
      stringio (>= 0)
      Available/installed versions of this gem:
      - 3.1.2
      - 3.0.4
WARN: Clearing out unresolved specs. Try 'gem cleanup <gem>'
Please report a bug if this causes problems.

*** LOCAL GEMS ***

reline (0.6.0, default: 0.3.2)

このあと、stringioのバージョンを3.1.2や3.0.4に変更して試しましたが効果はなく、最終的にGemfileに以下の記述を加えることで解決しました。

Gemfile
gem 'reline', '~> 0.3.2'

これは「relineを0.3.2以上かつ0.4.0未満でインストールする」という意味です。実際に使用していたrelineのバージョン0.6.0は debug と互換性がなかったようで、バージョンを ~> 0.3.2 に固定したところ問題が解消しました。

Gravatar

Gravatarとは、メールアドレスと画像を紐づける無料のサービスです。サンプルアプリケーションではこれを使用して、プロフィール画像を表示しています。
app/views/users/show.html.erb でGravatarを呼び出し、その実装を app/helpers/users_helper.rb に書きました。

show.html.erb
<% provide(:title, @user.name) %>
<h1>
  <%= gravatar_for @user %>
  <%= @user.name %>
</h1>
module UsersHelper
  # 引数で与えられたユーザーのGravatar 画像を返す
  def gravatar_for(user)
    gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
    gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}"
    image_tag(gravatar_url, alt: user.name, class: "gravatar")
  end
end

ここではRuby標準ライブラリの Digest モジュールにある hexdigest メソッドを用いて、ユーザーのメールアドレスをMD5ハッシュ化し、その値を用いてGravatarのURLを生成しています。

ユーザー登録フォーム

次に、他のユーザーがブラウザ上で新規登録できるようにフォームを作成しました。
まず、app/controllers/users_controller.rbdef new@user を生成し、続いて app/views/users/new.html.erb にフォームのレイアウトを追加します。

users_controller.rb
class UsersController <ApplicationController
  def show
    @user =User.find(params[:id])
  end
  def new
    @user =User.new # 追加
  end
end
new.html.erb

<% provide(:title,'Signup') %>
<h1>Signup</h1>
<div class="row">
  <div class="col-md-6col-md-offset-3">
    <%= form_with(model:@user)do |f| %>
      <%= f.label :name %> 
      <%= f.text_field :name %>

      <%= f.label :email %>
      <%= f.email_field :email %>

      <%= f.label :password %>
      <%= f.password_field :password %>

      <%= f.label :password_confirmation, "Confirmation"%>
      <%= f.password_field :password_confirmation %>

      <%= f.submit "Createmyaccount", class: "btnbtn-primary"%>
    <% end %>
  </div>
</div>

<% %> の中にRubyの処理を書けるのは便利で、Railsの特徴の一つですね。
このフォームでは、名前・メールアドレス・パスワード・パスワード確認の入力欄を用意しています。form_withを呼び出すとRails内のFormBuilderがfというオブジェクトを生成し、これを使って手軽にフォーム要素を生成できるようになっています。

ユーザー登録失敗

ここでは、Strong Parametersについて学びました。
以下のように、コントローラで User.new(params[:id]) のようにparamsをまるごと渡してしまうと、ユーザーがリクエストに admin: "1" を仕込むだけで管理者権限を奪えてしまいます。

users_controller.rb
def crate
@user = User.new(params[:id])
if @user.save
.
.
end

この問題を防ぐため、RailsではStrong Parametersという仕組みを使います。コントローラ内でparamsのうち許可したキーのみを受け取り、ホワイトリスト化された安全なデータだけをモデルに渡します。

users_controller.rb
class UsersController <ApplicationController
  .
  .
  .
  def create
    @user =User.new(user_params)
    if @user.save
      #保存の成功をここで扱う。
    else
      render 'new',status::unprocessable_entity
    end
  end

  private

    def user_params
      params.require(:user).permit(:name,:email, :password, :password_confirmation)
    end
end

また、private メソッドにすることで、コントローラ外から user_params を直接呼び出せないようにしています。

まとめ

7章あたりから難易度が上がってきたように感じます。
8章が終わったら、また1章から復習を始めようと思います。継続して取り組みながら、理解を深めていきたいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?