質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

479閲覧

バリデーション が機能しない

divclass123

総合スコア35

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2020/12/06 04:22

編集2020/12/07 06:32

前提・実現したいこと

投稿にバリデーション をかけてるのですが、上手くいきません、、、

コーヒーに関する投稿の名前、値段、タグ、コーヒーの説明、画像を
必須にすべくバリデーション をかけてるのですが、何も入力しないで投稿ボタンを押すと
空のままsaveされてroot_pathにリダイレクトされます。

空のままsaveされてるのかと思いましたが、例えば、名前だけ入力したら
データベースに保存されません。

全部のデータを過不足なくしっかり入力して投稿ボタン押したら
保存されました。

まだ入力されないなら、エラーメッセージを表示したいのですが、エラーハンドリングされずに
root_pathにリダイレクトされます。

該当のソースコード

drinks/new.html.erb

erb

1<div class="items-sell-contents"> 2 3 <div class="items-sell-main"> 4 <h2 class="items-sell-title">商品の情報を入力</h2> 5 <%= form_with model: @drink,url: drinks_path, local: true do |f| %> 6 7 8 <%= render 'shared/error_messages', object: f.object %> 9 10 <div class="tag-field" , id='tag-field'> 11 <%= f.label :tag_name %> 12 <%= f.text_field :tag_name %> 13 </div> 14 <div id="search-result"> 15 </div> 16 <div class="img-upload"> 17 <div class="weight-bold-text"> 18 出品画像 19 <span class="indispensable">必須</span> 20 </div> 21 <div class="click-upload"> 22 <p> 23 クリックしてファイルをアップロード 24 </p> 25 <%= f.file_field :image, id:"item-image" %> 26 </div> 27 </div> 28 29 <div class="new-items"> 30 <div class="weight-bold-text"> 31 商品名 32 <span class="indispensable">必須</span> 33 </div> 34 <%= f.text_area :name, class:"items-text", id:"item-name", placeholder:"商品名(必須 40文字まで)", maxlength:"40" %> 35 <div class="items-explain"> 36 <div class="weight-bold-text"> 37 商品の説明 38 <span class="indispensable">必須</span> 39 </div> 40 <%= f.text_area :explain, class:"items-text", id:"item-info", placeholder:"コーヒーの感想(必須 1,000文字まで)",rows:"7" ,maxlength:"1000" %> 41 </div> 42 </div> 43 44 <div class="price-content"> 45 <div class="price-text"> 46 <span>価格</span> 47 <span class="indispensable">必須</span> 48 </div> 49 <span class="sell-yen">¥</span> 50 <%= f.text_field :price, class:"price-input", id:"item-price", placeholder:"例) 1000" %> 51 </div> 52 53 54 55 56 57 <div class="sell-btn-contents"> 58 <%= f.submit "投稿する" ,class:"sell-btn" %> 59 <%=link_to 'もどる', root_path, class:"back-btn" %> 60 </div> 61 62 </div> 63 <% end %> 64

drinks_controller

ruby

1class DrinksController < ApplicationController 2 include SessionsHelper 3 4 before_action :logged_in_user, only: [:index,:destroy] 5 def index 6 @user = current_user 7 @drinks = Drink.all.order("created_at DESC") 8 end 9 10 def show 11 @drink = Drink.find(params[:id]) 12 @user = @drink.user 13 end 14 15 def new 16 @drink = DrinkTag.new 17 end 18 19 def create 20 @drink = DrinkTag.new(drink_params) 21 if @drink.save 22 redirect_to drinks_path 23 else 24 render 'new' 25 end 26 end 27 28 def destroy 29 Drink.find(params[:id]).destroy 30 redirect_to root_path 31 end 32 33 # GET search 34 def search 35 return nil if params[:keyword] == "" 36 # 何も入れず検索したらエラーが起こるので、 37 # 明示的にnilを返す 38 tag = Tag.where(['tag_name LIKE ?',"%#{params[:keyword]}%"]) 39 # 第二引数が第一引数の?に入っていく,検索した 40 # タグがデータベースにあれば返す 41 render json:{ keyword: tag} 42 # const tagName = XHR.response.keyword 43 # の.keywordが使えてる 44 45 end 46 47 48 private 49 def drink_params 50 params.require(:drink_tag).permit(:name,:price,:explain,:image,:tag_name).merge(user_id: current_user.id) 51 end 52end

drink_tag.rb

ruby

1class DrinkTag 2 3 include ActiveModel::Model 4 5 attr_accessor :name,:price,:explain,:image,:user_id,:tag_name 6 7 with_options presence: true do 8 validates :explain 9 validates :price 10 validates :name 11 validates :image 12 validates :tag_name 13 # tagとdrinkでnameってカラム名かかってるけど 14 # どっちも今のところpresense: trueでいいけど 15 # タグ付けしなくても投稿できるけど 16 # drinkの名前が必要ってなったらどうする 17 # drink[:name]とかで、drinkのnameにだけ 18 # バリデーション かけることは可能? 19 end 20 21 def save 22 drink = Drink.create(name: name,price: price,explain: explain,image: image,user_id: user_id) 23 tag = Tag.where(tag_name: tag_name).first_or_initialize 24 # .first_or_initializeはwhereで検索した条件の 25 # レコードがあれば、そのレコードのインスタンスを返し、 26 # なければ新しくインスタンスを作るメソッドです。 27 28 # tag.rbでtag_nameで一意性の制約をしていて 29 # 被った時に弾いちゃうから.first_or_initialize 30 # が必要 31 32 tag.save 33 DrinkTagRelation.create(drink_id: drink.id, tag_id: tag.id) 34 end 35 36end

shared/error_messages

ruby

1<% if object.errors.any? %> 2 <div id="error_explanation"> 3 <div class="alert alert-danger"> 4 The form contains <%= pluralize(object.errors.count, "error") %>. 5 </div> 6 <ul> 7 <% object.errors.full_messages.each do |msg| %> 8 <li><%= msg %></li> 9 <% end %> 10 </ul> 11 </div> 12<% end %>

tag.js

js

1if (location.pathname.match("drinks/new")){ 2 3 document.addEventListener("DOMContentLoaded",()=>{ 4 5 const inputElement = document.getElementById("drink_tag_tag_name") 6 7 inputElement.addEventListener("keyup",()=>{ 8 9 const keyword = document.getElementById("drink_tag_tag_name").value; 10 11 const XHR = new XMLHttpRequest(); 12 13 XHR.open("GET",`search/?keyword=${keyword}`,true); 14 15 XHR.responseType = "json"; 16 17 XHR.send(); 18 19 XHR.onload = () => { 20 21 22 const searchResult = document.getElementById("search-result"); 23 // 1.タグを表示させる場所である,search-resultを取得 24 searchResult.innerHTML = ""; 25 26 if (XHR.response){ 27 // イベントに指定したkeyupは、バックスペースキー 28 // などの押しても文字入力されないキーでも発火してしまう 29 30 // 存在しないものをtagNameに定義するとエラーが起こる 31 32 // レスポンスにデータがある場合のみタグを表示させる処理を行おう 33 34 const tagName = XHR.response.keyword; 35 36 tagName.forEach((tag) => { 37 38 const childElement = document.createElement("div"); 39 40 childElement.setAttribute("class", "child"); 41 childElement.setAttribute("id", tag.id); 42 43 childElement.innerHTML = tag.tag_name; 44 45 const clickElement = document.getElementById(tag.id); 46 47 clickElement.addEventListener("click",()=>{ 48 49 document.getElementById("drink_tag_tag_name").value = clickElement.textContent; 50 51 }); 52 }); 53 }; 54 }; 55 }); 56 }); 57};

試したこと

rails cで

19: def create 20: @drink = DrinkTag.new(drink_params) => 21: binding.pry 22: if @drink.save 23: redirect_to drinks_path 24: else 25: render 'new' 26: end 27: end [1] pry(#<DrinksController>)> @drink => #<DrinkTag:0x00007fb58c414080 @explain="", @name="", @price="", @tag_name="", @user_id=6> [2] pry(#<DrinksController>)> @drink.save CACHE User Load (0.0ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 6 LIMIT 1 [["id", 6], ["LIMIT", 1]] ↳ app/models/drink_tag.rb:22:in `save' Tag Load (0.2ms) SELECT `tags`.* FROM `tags` WHERE `tags`.`tag_name` = '' ORDER BY `tags`.`id` ASC LIMIT 1 ↳ app/models/drink_tag.rb:23:in `save' DEPRECATION WARNING: Uniqueness validator will no longer enforce case sensitive comparison in Rails 6.1. To continue case sensitive comparison on the :tag_name attribute in Tag model, pass `case_sensitive: true` option explicitly to the uniqueness validator. (called from save at /Users/soichirohara/coffee_passport/app/models/drink_tag.rb:32) (0.1ms) BEGIN ↳ app/models/drink_tag.rb:32:in `save' Tag Exists? (0.2ms) SELECT 1 AS one FROM `tags` WHERE `tags`.`tag_name` = BINARY '' AND `tags`.`id` != 8 LIMIT 1 ↳ app/models/drink_tag.rb:32:in `save' (0.1ms) COMMIT ↳ app/models/drink_tag.rb:32:in `save' (0.1ms) BEGIN ↳ app/models/drink_tag.rb:33:in `save' Tag Load (0.2ms) SELECT `tags`.* FROM `tags` WHERE `tags`.`id` = 8 LIMIT 1 ↳ app/models/drink_tag.rb:33:in `save' (0.1ms) ROLLBACK ↳ app/models/drink_tag.rb:33:in `save' => #<DrinkTagRelation:0x00007fb56d0297c8

と、saveメソッドが起動してしまうのが確認できました

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2020/12/06 06:17

どういうバリデーションをしているつもりなのか、要件を説明してください。
okuramasafumi

2020/12/06 12:28

`save`メソッドの先頭に`validate`メソッドの呼び出しを書けば動作はするかもしれません。 しかし、全体的に不明点が多いです。 例えば、「saveメソッドが起動してしまう」というのは意味を成していません、起動後の結果が重要なので。 「うまくいきません」ではなんの説明にもなりませんので、「何をしたくて何を期待していて何が期待と違うのか」をできるだけ明瞭に記述するように努力してください。
divclass123

2020/12/06 14:06

バリデーションが掛かってないのを掛かるようにしたいです。 フォームに入力しなくても投稿ボタンを押したら、保存されてしまいます。 投稿ボタンを押した時に、しっかりバリデーションがかかって、エラーハンドリングがされるって感じの事を期待してますが、そうはなりません。 すいません、saveメソッドの先頭にvalidateというのは具体的にどう言う基準でしょうか?
divclass123

2020/12/06 14:10

saveメソッドの起動後は恐らく、binding.pryの実行結果にあると思うのですが、不十分でしたでしょうか?
guest

回答1

0

自己解決

drinks_controller

で 

def create @drink = DrinkTag.new(drink_params) if @drink.save redirect_to drinks_path else render 'new' end end

def create @drink = DrinkTag.new(drink_params) if @drink.valid? @drink.save redirect_to drinks_path else render 'new' end end

と記述すべきだった

投稿2020/12/07 06:45

divclass123

総合スコア35

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問