LoginSignup
0
0

More than 1 year has passed since last update.

【Ruby on Rails】バリデーションが効かなかったときの原因追求をした話

Posted at

対象者

  • バリデーションを使っている方
  • バリデーションが効かない不具合が発生している方

目的

  • バリデーションを使って投稿が失敗するようにすること

実際の手順と実例

1.前提

上記記事を参考に実装

  • Articleモデル(記事の投稿)、Tagモデル、ArticleTagモデル(中間テーブル)実装中
  • title,bodyはArticleのカラム、tag_nameはTagのカラム

 下記のようにバリデーションを設定したが投稿ができてしまう、、、

model/tag.rb
class Tag < ApplicationRecord
  has_many :articles, through: :article_tags
  has_many :article_tags

  validates :tag_name, presence: true
end

2.結論(解決策)

下記のようにコントローラーを変更

before

app/tags_controller.rb
def create
    @article = Article.new(article_params)
    @article.user = current_user
    tag_list = params[:article][:tag_name].split("/")
    if @article.save
      @article.tags_save(tag_list)
      flash.now[:notice] = "投稿されました"
      redirect_to article_path(@article)
    else
      @user = current_user
      flash.now[:alert] = "投稿に失敗しました"
      render :new
    end
  end

after

app/tags_controller.rb
def create
    @article = Article.new(article_params)
    @article.user = current_user
    tag_list = params[:article][:tag_name].split("/")

      #下記の部分を追加
    if tag_list == []
      tag = Tag.new()
      tag.tag_name = ""
      tag.save
      @user = current_user
      flash.now[:alert] = "投稿に失敗しました"
      render :new
      #上記の部分を追加

    elsif @article.save
      @article.tags_save(tag_list)
      flash.now[:notice] = "投稿されました"
      redirect_to article_path(@article)
    else
      @user = current_user
      flash.now[:alert] = "投稿に失敗しました"
      render :new
    end
  end

※上記のコントローラーで使用しているtags_save(tag_list)はArticleモデルで定義したものです。

app/model/articles.rb
 def tags_save(tag_list)
    if !tags.nil?
      article_tags_records = ArticleTag.where(article_id: id)
      article_tags_records.destroy_all
    end

    tag_list.each do |tag|
      inspected_tag = Tag.where(tag_name: tag).first_or_create #①
      tags << inspected_tag
    end
  end

3.原因

@article.saveで保存が行われてしまっている

beforeの書き方だと先にarticleの内容が保存されてしまっており、
tag_saveも””空欄が保存され、そのまま通過してしまっている

[7] pry(main)> tag.tag_name = ""
=> ""

空欄だと投稿は失敗ですよということを表すために、
下記の記述を追加

app/tags_controller.rb
    if tag_list == [] #タグが空欄だったときの条件付け
      tag = Tag.new()
      tag.tag_name = "" #タグ名が空欄であることを定義
      tag.save #セーブされ、ここでバリデーションが作動する
      @user = current_user
      flash.now[:alert] = "投稿に失敗しました"
      render :new 
    elsif
      (中略)
       end

バリデーションが作動するのは.saveされたとき!ということを学びました、、!

0
0
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
0
0