説明
自分はformオブジェクトを用いてタグ機能は実装したのですが、投稿はともかく編集、削除、検索などは記事が少なく、あっても複雑で苦労したのでいくつかに分けて投稿したいと思います。
前提条件
あくまで記事が少なく複雑な部分をアウトプットしたので、ルーティング、コントーラー、モデル、アソシエーションなどは記載しますが、作る手順は省略します
完成コード
```tweets_controller.rb def new @tweet = TweetsTag.new enddef create
@tweet = TweetsTag.new(tweet_params)
tag_list = params[:tweets_tag][:name].split(',')
if @tweet.valid?
@tweet.save(tag_list)
redirect_to :root
else
render new_tweet_path
end
end
private
def tweet_params
params.require(:tweets_tag).permit(:title, :image, :text, :job_id, :status_id, :name).merge(user_id: current_user.id)
end
```tweets_tag.rb
def save(tag_list)
tweet = Tweet.create(title: title, text: text, image: image, job_id: job_id, status_id: status_id, user_id: user_id)
tag_list.each do |tag_name|
tag = Tag.where(name: tag_name).first_or_initialize
tag.save
TweetTagRelation.create(tweet_id: tweet.id, tag_id: tag.id)
end
end
<div class="field">
<%= f.label :name, "タグ(タグ同士の間には半角の「,」を入れてください)", {class: 'motivate-label'} %><br />
<%= f.text_field :name, placeholder: "(例)ドラマ,医療,社会", :class => 'motivate-field' %>
</div>
コード解説
```tweets_controller.rb def new @tweet = TweetsTag.new end ```まずコントローラーに新規投稿用の空のインスタンスを作ってあげます。以前はTweetモデルから作っていたと思いますが、それをformオブジェクト用に作ったモデルを指定して作ります。
<div class="field">
<%= f.label :name, "タグ(タグ同士の間には半角の「,」を入れてください)", {class: 'motivate-label'} %><br />
<%= f.text_field :name, placeholder: "(例)ドラマ,医療,社会", :class => 'motivate-field' %>
</div>
投稿ページにてタグを入力する部分を追加します。:nameの部分は自分のtagsテーブルのカラム名にしましょう。またタグを複数投稿にしたい場合は入力説明に複数投稿の際区切る指示を記載しておきましょう。自分の場合はタグ同士は半角の「,」で区切るようにこの後設定するのでそのように記載しています。
def new
@tweet = TweetsTag.new
end
def create
@tweet = TweetsTag.new(tweet_params)
tag_list = params[:tweets_tag][:name].split(',')
if @tweet.valid?
@tweet.save(tag_list)
redirect_to :root
else
render new_tweet_path
end
end
private
def tweet_params
params.require(:tweets_tag).permit(:title, :image, :text, :job_id, :status_id, :name).merge(user_id: current_user.id)
end
1.先ほどの投稿画面で送信して内容は一般的な投稿機能のようにcreateアクションに送られます。違うのは、privateにformオブジェクト用のparamsのメソッドを作成します。requireにはformオブジェクトのモデルを指定します。加えて、permitにtagsテーブルのカラムのnameを追加してます。
2.1で作ったtweet_paramsを使って、新たなformオブジェクトのインスタンスを生成し、@tweetに代入します。そして、送信されたタグを一個づつtag_listに配列として代入していきます。
``` params[:tweets_tag][:name].split(',') ```の部分はparamsが二重の配列になっているので:tweets_tagのname配列の中身をは.split(',')によって「,」が入力されている部分で区切って分けるという記述です。
3.@tweet.valid?を通った場合いよいよ保存です。
``` @tweet.save(tag_list) ```の記述によって配列として一つ一つタグが入っているtag_listを引数として持っていてsaveを行いますが、このまま普通のsaveをして意味がないのでformオブジェクトのモデル内に正しく保存できるように新たなsaveメソッドを定義します。
def save(tag_list)
tweet = Tweet.create(title: title, text: text, image: image, job_id: job_id, status_id: status_id, user_id: user_id)
tag_list.each do |tag_name|
tag = Tag.where(name: tag_name).first_or_initialize
tag.save
TweetTagRelation.create(tweet_id: tweet.id, tag_id: tag.id)
end
end
ここでまず、tweetモデルにだけツイート内容を作る作業を行います。
``` tweet = Tweet.create(title: title, text: text, image: image, job_id: job_id, status_id: status_id, user_id: user_id) ```この記述はtweetモデルの各カラムを指定してattr_accessorに書いた内容を保存しています。
``` tag_list.each do |tag_name| tag = Tag.where(name: tag_name).first_or_initialize tag.save TweetTagRelation.create(tweet_id: tweet.id, tag_id: tag.id)
end
<p>この部分では引数によって持ってきたtag_listの中身を一つ一つ取り出して、初めてのものならtagsテーブルに保存、tagとtweetとの中間テーブルにも保存するといった記述です。</p>
<h2>まとめ</h2>
<p>以上が複数タグを保存する記述の解説となります。この後編集、削除、フロント、タグ関連の投稿一覧、タグの検索の記事を投稿していこうと思います。閲覧ありがとうございました。</p>