ユーザークリップの作成ページからurlを入力すると、ユーザークリップとクリップの両方を作成できるようにします。
ユーザークリップコントローラを使用して、ユーザークリップとクリップの両方を作成します。作成は、クリップと同じくurlのみの入力で作成できるようにします。
また、ユーザークリップはログインユーザーのみが使用できるように認証機能を追加しましょう。
before_action :authenticate_user! という1文をコントローラの先頭に記述することで、そのコントローラ内のアクションはログインユーザーのみが実行できるようになります。
、今回はuser_clips_controller.rbに認証を追加します。以下を追加して下さい。
# user_clips_controller.rb
class UserClipsController < ApplicationController
before_action :authenticate_user!
では、ユーザークリップ作成ページのフォームを編集していきます。scaffoldによって自動でユーザークリップの_form.html.erbが作成されています。現在のユーザークリップの作成ページを確認してみましょう。
を開いて下さい。今回はURLのみを送るフォームなのでユーザーidやクリップidを入力するフォームは以下は部分は必要ありません。ユーザークリップの_form.html.erbを編集しましょう。
ファイルを開いて以下の緑部分を削除して下さい。緑部分を削除して下さい。
# user_clips/_form.html.erb
<div class="field">
<%= form.label :user_id %>
<%= form.text_field :user_id %>
</div>
<div class="field">
<%= form.label :clip_id %>
<%= form.text_field :clip_id %>
</div>
そして、現状のフォームでははscaffoldによってユーザークリップモデルファイル内の属性が確認され、自動的にuser_idとclip_id のフォームが作成されています。
【ユーザークリップモデルファイル 画像】がフォームになっていて、
しかし、ユーザークリップモデルファイルにはURLという属性がない為、URLを送信するフォームがはありません。これを、以下のようにURL送信フォームに変更しましょう。
【変更前後 画像】
コードは以下のようになります。
<%= form_with(model: user_clip, local: true) do |form| %>
<div class="field">
<%= label_tag :url %>
<%= text_field_tag :url %>
</div>
<% end %>
今回は、上記のようにtext_field_tagでフォームを作成しています。これは、モデルに関連していない属性を扱うフォームの場合に使用するものです。今回のURLという属性はユーザークリップモデルには存在しない属性の為、text_field_tagを使っています。
では、フォームから送信されたURLがどのように扱われるのかを見ていきましょう。URLは以下図のように、ユーザークリップコントローラのcreateアクションに送られます。
そして、URLでクリップデータベースを検索してクリップを取得します。取得したクリップは、以下のようにインスタンス変数に代入します。
@clip = Clip.find_by(url: params[:url])
では、実際にuser_clips_controller.rbにコードを書いていきます。先ほどのように@clipというインスタンス変数などを記述していくのですが、これだけだとクリップデーターベースに存在しないURLの場合は、見つからないとエラーが出てしまいます。
ですので、クリップがあればそのクリップを使って、そうでなじゃなければ新しくクリップを作成するというようにします。実際のコードは以下です。
def create
@clip = Clip.find_by(url: params[:url])
unless @clip
@clip = Clip.new(url: params[:url])
end
end
このコードで、クリップが存在する場合とそうでない場合で処理を切り分ける事が出来るようになりましたが、このコードは以下のように1行で書くこともできるのです。
@clip = Clip.find_or_initialize_by(url: params[:url])
コントローラに書くコードは少ない方が良いので、今回は1行で書くことにします。
4.initializeについて
find_or_create_byは、findをかけて引っかからなかったらcreateする。
find_or_initialize_byは、findをかけて引っかからなかったらnewする。
というメソッドです。
今回はクリップがあればそのクリップを使って、クリップがなければ新しくクリップを作成なのでfind_or_initialize_byを使っています。
クリップを検索もしくは作成した後は、クリップとユーザーに紐づくユーザークリップを作成して、クリップとユーザークリップを保存します。以下部分を追加して下さい。
@clip = Clip.find_or_initialize_by(url: params[:url])<br>
@user_clip = current_user.user_clips.build(clip: @clip)<br>
<br>
respond_to do |format|<br>
if @clip.save && @user_clip.save
では、/user_clips/newにアクセスしてブラウザで作成できるか確認しましょう。
作成・保存までは完成しましたので、最後にリダイレクトの設定を行います。今回はユーザークリップ作成後にuser_clips#indexにリダイレクトするようにしましょう。以下のように変更して下さい。
respond_to do |format|
if @clip.save && @user_clip.save
format.html { redirect_to user_clips_url, notice: '...' }
アーティクルにカテゴリーを実装しましょう。New Articleで、カテゴリーが追加できるようにフォームを追加してみて下さい。そして、出来ているかどうかコンソールで確認して下さい。
無料ビデオ講座のお知らせ
Skillhub [スキルハブ]では無料の動画講座を多数公開しています。他校だと数万円するような講座が無料で受講できます。