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

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を登録するフォームもあります。

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

モデルに紐付かないフォームの作成
今回は通常のフォームとは違いモデルと紐づきません。以前作成したフォームは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のデータを検索します。

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行で表現することができます。

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

上のようなデータを作成するためには以下のようなコードになります。
# 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にリダイレクトされれば成功です。