自分のクリップを作成する | SkillhubAI(スキルハブエーアイ)

自分のクリップを作成する

自分のクリップを作成する

ユーザークリップの作成ページからurlを入力すると、ユーザークリップとクリップの両方を作成できるようにします。

今回の作成方法

ユーザークリップコントローラを使用して、ユーザークリップとクリップの両方を作成します。作成は、クリップと同じくurlのみの入力で作成できるようにします。

file

1.認証機能の追加 before_action :authenticate_user!

また、ユーザークリップはログインユーザーのみが使用できるように認証機能を追加しましょう。

before_action :authenticate_user! という1文をコントローラの先頭に記述することで、そのコントローラ内のアクションはログインユーザーのみが実行できるようになります。

今回はuser_clips_controller.rbに認証を追加します。以下を追加して下さい。

# user_clips_controller.rb

class UserClipsController < ApplicationController
  before_action :authenticate_user!

2.ユーザークリップのフォーム

では、ユーザークリップ作成ページのフォームを編集していきます。scaffoldによって自動でユーザークリップの_form.html.erbが作成されています。現在のユーザークリップの作成ページを確認してみましょう。

user_clips/newにアクセスすると以下のようにユーザーのIDを登録するフォームもあります。

file

ですが今回はこの入力フォーム部分は必要ありません。下のように自分が気に入ったページのURLだけを登録できるようにします。

file

モデルに紐付かないフォームの作成

今回は通常のフォームとは違いモデルと紐づきません。以前作成したフォームはClipやArticleのフォームはモデルに紐付いていましたね。しかし今回はクリップするためにURLだけを送信するフォームを作成します。このような「ただのフォーム」みたいなものを作成したいことは良くありますので、ぜひ覚えておいてください。

まずは_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>
##### ここまでを削除 #######

今回はモデルと紐付かずURL情報だけを送りたいのでtext_field_tagというメソッドを使います。 コードを以下のように変更してください。モデルに紐づく場合はform.などに続く形になります。日もつかない場合はtext_field_tagと書くだけです。

モデルに紐づく場合<%= form.text_field :clip_id %>
そうではない場合<%= text_field_tag :url %>

その部分を書くと以下のコードになります。label部分も:urlに直すのお忘れないようにしましょう。

  <div class="field">
    <%= label_tag :url %>
    <%= text_field_tag :url %>
  </div>

送られてきたURLからデータ処理

今回は送られてきたURLから2つのデータを処理します。 1つはClipのデータ、もうひとつはUserClipのデータになります。

Clipのデータ処理

Clipのデータ処理は

1. 送られてきたURLがすでに存在すれば、そのデータを返す
2. URLが存在しなければ新しいClipデータ(レコード)を作成する

という処理になります。以下の図のようにパラメータで送られてきたURLからClipのデータを検索します。

file

ClipのURLを検索するコードは以下のようになります。

@clip = Clip.find_by(url: params[:url])

検索してURLが存在した場合はそれを返す。 URLが存在しない場合は新しくClipを作成するコードは以下になります。

def create
  # URLを検索して@clipにデータを入れる
  @clip = Clip.find_by(url: params[:url])  

  # @clipがない場合(nil)は送られてきたURLから新たにClipを作成し@clipに入れる
  unless @clip
    @clip = Clip.new(url: params[:url])
  end
end

これを1行で書いてみる

上のコードでもまったく問題ないのですが、もっと短くコードを書くことができます。 以下の図のように今まで4行あったコードもたった1行で表現することができます。

file

このfind_or_initialized_byというメソッドを使うと「〜を見つけてくる、でもそれがない場合は新しいデータを作成する」といった処理を一行で書くことができるのです!素晴らしいですね。ぜひこちらを使ってみてください。

UserClipのデータ処理

UserClipのデータは「user_id」と「clip_id」を保存するためのものです。

file

上のようなデータを作成するためには以下のようなコードになります。

# clipを見つけるもしくは作成する
@user_clip = current_user.user_clips.build(clip: @clip)

保存までのすべてのコードを書くと以下のようになります。

@clip = Clip.find_or_initialize_by(url: params[:url])
@user_clip = current_user.user_clips.build(clip: @clip)

respond_to do |format|<br>
  if @clip.save && @user_clip.save
    format.html { redirect_to user_clips_url, notice: 'クリップは無事に作成されました' }    

では、/user_clips/newにアクセスしてブラウザで作成できるか確認しましょう。データを入力して保存するとuser_clips/indexにリダイレクトされれば成功です。