5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Rails6]Formオブジェクト+複数タグ機能での更新を実装

Posted at

はじめに

タグ機能実装中に、Formオブジェクトが絡んだタグの更新にとても苦戦したことと、しっくりくる記事が少なかったこともあったので執筆します。完全自作かつ非効率な実装方法かもしれませんがどうぞお付き合いください。
なお、もっとこうしたら簡単だよ!みたいなコメントをくださると嬉しいです。

#タグの更新で苦戦した部分
まず、今回苦戦したポイントとして、「Formオブジェクトはレコードとしては存在していない」というところです(あと、複数タグという点)。通常、なにかしらの更新をする際にはfindメソッドあるいはfind_byメソッドをつかって、欲しいデータを持ってくることができたはずです。
Formオブジェクト(例:item_address.rb)は実際にレコードがあるわけではないので、以下のようにはできません。

@item_address=ItemAdress.find(id:params[:id])

#解決策
じゃあ、どうすればいいのか。
答えは、newメソッドを使います。「レコードとして存在しない」は言い換えれば「指定する必要もない」ということで持ってくる必要はないので、だったらそのときに作ればよくね?って話です。
(ここまで意味が不明だと思いますが、お付き合いください)

Formオブジェクトについてしっかりとした理解があれば、以下のコードを見れば理解できると思います。

tweets_contoroller.rb
  def edit
    @tweets_tag=TweetAddress.new(title:@tweet.title,content:@tweet.content)
  end
  

まずはeditアクションに着目してみましょう。たしかに、newメソッドを使用しています。でも、これでしっかり欲しいデータが詰まったインスタンスが生成されます。実はFormオブジェクト自体はnewで作成されますが、Formオブジェクトの中身には、@tweetというbefore_actionでparams[:id]からfindメソッドで指定したインスタンスがデータとして入っているので、結果として指定したいFormオブジェクトが出来上がっているわけです。

あとは、@tweets_tagを使えば編集ページは表現できます。

updateアクションの実装

引き続いて、編集ページで新たにタグが入力されたとします。そのとき、updateアクションはどのように記載すべきでしょうか。

これについては、コードを見た方が早いので以下を見てください。

tweets_controller.rb
#省略

def update
    @tweets_tag=TweetsTag.new(update_params)
    tag_list=params[:tweets_tag][:name].split(",")
    
    if @tweets_tag.valid?
      @tweets_tag.update(tag_list)
      redirect_to tweet_path(@tweet)
    else
      render :edit
    end
  end
tweets_tag.rb
#省略

 def update(tag_list)
    
  
    #tweetの更新
    @tweet = Tweet.where(id: tweet_id)
    tweet = @tweet.update(title: title,content: content)
    @old_relations=TweetTagRelation.where(practice_id:practice_id)
    #この時点で一旦中間テーブルのデータ消す
    @old_relations.each do |relation|
      relation.delete
    end  
    
    #tagの更新
    tag_list.each do |tag_name|
      @ptag = Tag.where(name: Tag_name).first_or_initialize
      @Tag.save
      #再度1個づつ中間テーブルへ登録
      new_relation=TweetTagRelation.new(tweet_id:tweet_id,ptag_id:@tag.id)
      new_relation.save
    end
 end  

ここでも、editアクション同様にnewメソッドとストロングパラメータを使って、インスタンスを持ってきていますね。
updateでのポイントは、自らでupdateメソッドを実装しないといけないところですね.流れとしては、tweetとtagをそれぞれ更新すると同時に、新たな中間テーブルのレコードを作成するようにするupdateメソッドをtweet_tag.rbに記載します。本当は既存の中間テーブルのレコードを消さずに更新できればもっと効率が上がるのですが、とりあえず今回は実装完了を目標としていますのでそこは割愛します。

なお、入力されたタグはparamsの中では1つの文字列として認識されますので、複数タグを入力するときは「,」で区切ってもらい、受け取った後にsplitメソッドで分割することに注意してください。

tag_list=params[:tweets_tag][:name].split(",")

おわりに

私自身も実装にかなり時間がかかってしまったのですが、終わってみるととてもシンプルでした。Formオブジェトパターンが関わると見慣れない記述方法も出てくるので、焦ってしまいがちですが、一呼吸おいてから考えてみるととてもシンプルで、Railsのすごさを感じれました!!!!

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?