アラサーOLだっしゅつけいかく

30代でOLを辞めて未経験からエンジニアになろうと一念発起した人の活動記録です

オリジナルアプリ開発#6 登録語詳細ページとアクセス制限

Lesson#12-2

必要なページがどんどん形になってきて楽しいです!!

自分で考えて作ったものがちゃんと動いて形になってくるのはやはりどんなものでも楽しいなぁ、って思います。
やっぱり私は作ることが好きみたいです!笑

さて、今回は登録した単語の詳細ページとログインユーザー以外が単語関係のページにアクセス出来ないよう制限をかける処理を作りました。

登録単語詳細ページ作成

一覧を作って登録できるところまで進めたので今度は登録単語の一覧を表示できるようにapp/views/words/show.html.erbを作成して編集していきます。

見た目の部分はBootstrapを使ってゴリゴリ作っていきます。簡単。楽しい。
一応レスポンシブを意識してレイアウトを考えて…います!

戻るボタンの実装

単語詳細ページから一覧に戻る時、検索結果やページネーションを維持するために前のページに戻るとしたいなぁと思って調べてみたらlink_toヘルパーを使えば良さそうということがわかりました。

<%= link_to 'back', :back %>

これでページネーションを保ったまま前のページに戻ることができました!

削除するときにアラートを出したい

  • ゴミ箱アイコンを押す
  • 削除していいかアラートが出る
  • 削除する
    • 登録語を削除して一覧に戻る
  • 削除しない
    • 詳細ページに戻る

というのを実装したいです。 data: {confirm: "表示させる文章"}をlink_toの中に追加すれば良いみたいなので

<%= link_to word_path, method: :delete, data: {confirm: "本当に削除しますか?"} do %>
  <%= fa_icon 'trash 2x' %>
<% end %>

インデックスの並び順を新しい順に並び替える

orderを使って作成日時が新しい順に表示されるようにしました。

 def index
    @words = self.user.words.order(created_at: :desc).page(params[:page]).per(24)
  end

単語詳細ページ

指摘事項

def user
  @user = current_user
end

と、メソッド化していた部分、そもそも@userに代入しなくてもcurrent_userだけでよかったんじゃない?と。

確かにそうです。

だってcurrent_userはもうdeviseを導入することで使えるヘルパーメソッドなんだもの。

なのでself.userとしていた部分をそのままcurrent_userに置き換えました。スッキリ!

登録語編集ページ作成

さて、LGTMを頂いたのでサクッとmasterにマージ後create_words_editpageというブランチを作成し、登録語編集ページを作成していきたいと思います。

フォームは新規作成と一緒なので、ページを作成後フォーム部分をパーシャルに切り分け呼び出すようにしました。
呼び出し部分は下記に置き換え。editページとnewページです。

<%= render "form" %>

同ビューフォルダ内に_form.html.erbというファイルを作成し、フォーム部分を移動させて、完了。

アクションを作る

ビフォアアクションにeditとupdateも加えてパラメータを取得

before_action :set_word, only: [:show, :destroy, :edit, :update]

updateアクションも作成!

def update
  if @word.update(words_params)
    redirect_to word_path, notice: '単語を編集しました!'
  else
    render 'show'
  end
end

ちゃんと更新できました〜。

ついでに変数名なども変更して(@words→@word)プルリクエストを作成しました。

今回のコメント

LGTM
ですが、コミットの粒度が大きすぎます。
コミットは細かく分けた方がいいです。
今回もwordsからwordへの修正とかフォームを部分テンプレートに切り分けたとかでコミットはわけられたはずです

確かに。
色々いじるのに夢中であれこれ触ってるうちに全部できたかな?って思って一回のコミットでプッシュしてプルリクエストをあげてました。
コミット=保険・履歴みたいなところがあるので、1個うまくいったら保存しておいて、いつでもその状態に戻せるようにしておいた方がいいですよね。

というわけで、次回からは細かくコミットしていこうと思いました。

アクセス制限をかける

自分のページには自分しか入れないようにアクセス制限をかけたいと思います。
masterブランチからaccess_permission_settingという新しいブランチを作成し作業を開始します。

このアプリの基本設計として、登録した単語の共有はしないことになっています。
なので、wordコントローラーにある単語の一覧機能や新規作成、編集、削除の機能などは全てログインユーザーのみがアクセスできればOK!
deviseのヘルパー機能でログインユーザー以外のアクセスを拒否するメソッドがあるので、それをwordコントローラーapp/controllers/words_controller.rbに追記しましょう。

before_action :authenticate_user!

ログインしてたらTOPページにアクセスできないようにする

今度は逆にログイン中にアプリのTOPページにアクセスできないように設定します。
左上のロゴをクリックするとrootに戻るように設定されていますが、ログイン中にここを押したら単語一覧ページが表示されるようにしたいです。

クリックした時ログイン中だったら単語一覧にリダイレクトする

という一文をStaticPagesのhomeアクションapp/controllers/static_pages_controller.rbに追記します。

def home
  redirect_to words_path if user_signed_in?
 end

ここで一旦プルリクエストを作成しました。

エラー表示の作成

ユーザー機能の方はdeviseによってエラー表示が出ますが、word投稿フォームの方はエラーが表示されません。
ここを作成していきます。

ブランチをmasterに戻して新しくdisplay_errorsというブランチを作成しました。

まず、エラーを表示する部分はapp/views/words/_error.html.erbとしてパーシャルで切り分けます。
呼び出す部分はフォームの上にしたいのでapp/views/words/_form.html.erbの一番上に下記のコードを追記しました。

<%= render 'error' %>

これでエラー部分を呼び出します。

app/views/words/_error.html.erbの方はエラーがあれば表示させる、ということで下記のようなコードにしました。

<% if @word.errors.any? %>
  <div class="alert alert-danger text-left m-4">
    <ul>
      <% @word.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
    </ul>
  </div>
<% end %>

エラーの表示

こんな感じでエラーが表示できました!
ちょっとブサイクですが細かいところはあとで整えることとして一旦これでOKとします。

更新時の挙動がおかしい?

更新時、なぜかフォームが空でも送信できてしまってさらに詳細ページにも空欄で表示される、でももう一回編集ボタンを押すとフォームに修正前のデータが入っていると言う謎の現象が起きていました。
その原因を探ってみました。

updateメソッドなのでバリデーションは通っているはずなんです。

…とよーーくみたら間違いはここでした。

 render 'show'

保存できなかった時の戻り先が詳細ページになっていたんですね。
これはフォームに戻さなければいけないのでeditです。

def update
  if @word.update(words_params)
    redirect_to word_path, notice: '単語を編集しました!'
  else
    render 'edit'
  end
end

updateアクションを修正してプルリクエスト作成しました。

レビューコメント

作成したプルリクエストについてのコメントです。
レビューしてもらう方に何をどういう意図でというのがきちんと伝わるように書かないとダメですね。
簡潔に文章を書こうとして、結果きちんと伝わらなかったということが起きたので次回より気をつけていきたいと思います。

単語登録機能の操作をログインユーザーにのみ許可

WHAT

  • 単語登録機能の操作をログインユーザーのみに許可
  • 左上のアイコンの遷移先をログイン時と非ログイン時で変更

これだと登録機能以外も制御されてしまうと思うのですが、
今回のPRって単語機能全体に制御をつける目的なのでしょうか。

今回のアプリは登録した単語の共有を他のユーザーとしない設計なので、ユーザー本人のみ単語の登録や閲覧、編集の機能を持たせたかったのでこういう書き方になるのかな?と思いました。
コメントの書き方があまり良くなかったでしょうか。

  • 単語登録に関わる全ての機能(閲覧、編集、削除)などの機能をログインユーザーのみに許可

と言うことです。

コメントの書き方があまり良くなかったでしょうか。

コメントがよくないですね。
曖昧、あるいは他の要素として捉えることができる表現は避けましょう。
こういうところがエンジニアの強みでもあるのかなと思ってます。

というやりとりがありました。
自分の意図がきちんと相手に伝わらなくて余計なやりとりが増えちゃってますね…!
気をつけます。。

エラー表示部分の作成

WHAT

  • エラー表示部分の作成
  • editアクションで保存失敗時の戻り先を修正

LGTM
部分テンプレート化グッドです 👍

こっちは一発OK頂きました!

次回からはちょっと山場

このアプリは大分シンプルな設計になっていると思いますが、その中で作るのが大変そうなのが

という部分だと思ってます。
次回からはその2つにチャレンジしていこうと思います!

まずは特定の文字列をリンクに変換して表示からやっつけます!!