yuufuji0000
@yuufuji0000 (yuu)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

中間テーブルが保存されずタグを配列として表示できない

中間テーブルを用いて投稿に紐ずくタグを配列として表示させたい

現在、投稿に紐ずくタグ付け機能を実装しているのですが、タグが配列として複数表示できるような実装をイメージしております。

配列としてタグを複数投稿できるような実装に変えたところ、今まで保存できていた中間テーブルが保存できないようになり、投稿にタグが表示されずにタグも配列として保存されずにひとかたまりにデーターベースに保存されてしまいます。

また、formオブジェクトを用いて複数のテーブルに保存される機能にしているため、どのような記述方法が正解なのか分からない状況です。

formオブジェクトやタグ付け機能などの詳しい方がおりましたら、ご教授願えますでしょうか。

発生している問題・エラーメッセージ

1・保存したタグが配列として取得できない
2・投稿テーブルとタグテーブルにおける中間テーブルの値が保存されない
3・投稿時にエラーが表示されるが、データベース常に値は保存されておりトップページに戻ると問題なく表示される

上記1、2のコンソール上の出力結果

[1] pry(#<UploadsController>)> UploadTagRelation.create
=> #<UploadTagRelation:0x00007fdb13f9cdb0 id: nil, upload_id: nil, tag_id: nil, created_at: nil, updated_at: nil>
[2] pry(#<UploadsController>)> params[:upload_form][:name]
=> "東京 渋谷 カフェ"
[3] pry(#<UploadsController>)> 

投稿時に表示されるエラー画面

NameError in UploadsController#create
undefined local variable or method `tag' for #<UploadForm:0x00007fdb25ceff38 @errors=#<ActiveModel::Errors:0x00007fdb25ced7b0 @base=#<UploadForm:0x00007fdb25ceff38 ...>, @errors=[]>, @title="カフェ", @text="タグカフェ", @url="", @working_day="", @day_off="", @cafe_wifi_id="1", @cafe_charging_id="1", @cafe_smoking_id="1", @image=#<ActionDispatch::Http::UploadedFile:0x00007fdb13eb42e0 @tempfile=#<Tempfile:/var/folders/gw/k3mqyqh15y37h56g1b17ymvc0000gn/T/RackMultipart20210514-85259-f73ob5.jpeg>, @original_filename="2f211d6f387d6006a68f.jpeg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"upload_form[image]\"; filename=\"2f211d6f387d6006a68f.jpeg\"\r\nContent-Type: image/jpeg\r\n">, @name="東京 渋谷 カフェ", @user_id=1, @validation_context=nil>
Did you mean?
tap
Extracted source (around line #32):
30
31
32
33
34
    end
    UploadTagRelation.create(upload_id: upload.id, tag_id: tag.id)⇦この部分
  end
end

 tag_list = params[:upload_form][:name].split(",")
    if @upload.valid?
      @upload.save(tag_list)⇦この部分
      redirect_to root_path
    else
      render new

該当のソースコード

app/controllers/upload_controller

class UploadsController < ApplicationController
  def index
    @uploads = Upload.all.order(created_at: :desc)
  end

  def new
    @upload = UploadForm.new
  end

  def create
    # binding.pry
    @upload = UploadForm.new(upload_params)
    tag_list = params[:upload_form][:name].split(",")
    if @upload.valid?
      @upload.save(tag_list)
      redirect_to root_path
    else
      render new
    end
  end

  def show
    @upload = Upload.find(params[:id])
    @tag = @upload.tags
  end

  def destroy
    @upload = Upload.find(params[:id])
    @upload.image.purge if @upload.image.attached?
    if @upload.destroy
      redirect_to root_path
    else
      render :show
    end
  end

  private

  def upload_params
    params.require(:upload_form).permit(:title, :text, :url, :working_day, :day_off, :cafe_wifi_id, :cafe_charging_id, :cafe_smoking_id, :image, :name).merge(user_id: current_user.id)
  end
end

app/models/form_model

class UploadForm
  include ActiveModel::Model
  attr_accessor :title, :text, :url, :working_day, :day_off, :cafe_wifi_id, :cafe_charging_id, :cafe_smoking_id,
                :user_id, :image, :name

  with_options presence: true do
    validates :title
    validates :text
    validates :cafe_wifi_id
    validates :cafe_charging_id
    validates :cafe_smoking_id
    validates :user_id
    validates :image
    validates :name
  end

  with_options numericality: { other_than: 0 } do
    validates :cafe_wifi_id
    validates :cafe_charging_id
    validates :cafe_smoking_id
  end

  def save(tag_list)
    upload = Upload.create(title: title, text: text, url: url, working_day: working_day, day_off: day_off, cafe_wifi_id: cafe_wifi_id, cafe_charging_id: cafe_charging_id, cafe_smoking_id: cafe_smoking_id, user_id: user_id, image: image)
    # tag = Tag.create(name: name)

    tag_list.each do |tag_name|
      tag = Tag.where(name: tag_name).first_or_initialize
      tag.save
    end

    UploadTagRelation.create(upload_id: upload.id, tag_id: tag.id)
  end
end

app/models/upload.rb

class Upload < ApplicationRecord
  has_one_attached :image
  has_one :map
  belongs_to :user
  has_many :upload_tag_relations, dependent: :destroy
  has_many :tags, through: :upload_tag_relations, dependent: :destroy
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to :cafe_smoking
  belongs_to :cafe_charging
  belongs_to :cafe_wifi
end

app/models/upload_tag_relation.rb

class UploadTagRelation < ApplicationRecord
  belongs_to :tag
  belongs_to :upload
end

app/models/tag.rb

class Tag < ApplicationRecord
  has_many :upload_tag_relations
  has_many :uploads, through: :upload_tag_relations

  validates :name, uniqueness: true
end

試したこと

*コントローラーのcreateアクションの記述に誤りがないか確認してみたところ、@upload=UploadForm.new(upload_params)でformオブジェクトモデルを渡しているので中間テーブルは保存されるはずができない。
tag_list = params[:upload_form][:name].split(",")で配列として処理される記述にしているが、まとまって出力されてしまう。
*formオブジェクト内でUploadTagRelation.create(upload_id: upload.id, tag_id: tag.id)と記述しているが中間テーブルが保存されない

補足情報(FW/ツールのバージョンなど)

開発環境
・rubymine
・ruby(3.0.1)
・Ruby on rails (6.1.3.1)

0

1Answer

    tag_list.each do |tag_name|
      tag = Tag.where(name: tag_name).first_or_initialize # ここで作った `tag` を使っていない
      tag.save
    end

    UploadTagRelation.create(upload_id: upload.id, tag_id: tag.id)
    tag_list.each do |tag_name|
      tag = Tag.where(name: tag_name).first_or_initialize # ここで作った `tag` を使っていない
      tag.save

      UploadTagRelation.create(upload_id: upload.id, tag_id: tag.id)
    end

のように,tag を使うようにするのはどうでしょうか?

0Like

Your answer might help someone💌