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

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

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

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

Ruby on Rails

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

Q&A

解決済

2回答

10017閲覧

エラーメッセージが表示できない。ドットインストールのRails課題TaskAppにて

nok2015

総合スコア13

Ruby

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

Ruby on Rails

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

0グッド

3クリップ

投稿2015/10/27 00:54

編集2015/10/27 00:55

プログラミング歴1ヶ月の初心者です。

どのぐらい初心者かというと、Railsチュートリアルをわけもわからず写経してツイッターもどきを作ったことはあるものの、MVCを漠然と理解しはじめた程度の状態です。

昨日はVagrantでローカル開発環境を四苦八苦しながら作って「rails new」するのに丸一日使ってしまった、そんなレベルです。

さて、今回は初めてteratailで質問させていただきます。

昨夜、ドットインストールのRailsコースをやり終わりました。「TaskApp」というタスク管理アプリをサンプルとして進めていく動画授業です。

理解不明な部分も多々ありますが、ひととおりドットインストールを写経して、少しだけアレンジを加えてみようと思いましたが、どうしてもうまくできないので教えてください。

★ドットインストールのサンプルアプリの説明
このサンプルアプリ「TaskApp」はシンプルな仕様で、各プロジェクトの中にタスクがあり、各プロジェクトの管理画面でタスクを複数追加できる、というものです。

ドットインストールの動画では、プロジェクトを追加するcreateの際にバリデーションを適用して、「入力してください」や「4文字以上は必須です!」などのエラーメッセージが表示できるようにしています。

それと似たような感じのオリジナル機能を実装したいのですが、ここでハマっています。
タスク登録の際、空白でsubmitボタンを押したら「空白では登録できません!」という文字を表示したいと思ったのですが、どうしてもできませんでした。

アドバイスをいただけるとうれしいです。よろしくお願いします。

添付画像はshow.html.erbです。(teratailは画像は1枚しか添付できないのでしょうか?)
イメージ説明

###前提・実現したいこと
task登録フォームに空白を入れたままsubmitボタンを押したら、”空白では登録できません!”と表示できるようにしたい

###発生している問題・エラーメッセージ
createメソッドnewとsaveを同時におこなうメソッドですからバリデーションエラー理由で保存できなかった場合、@taskにはfalseとエラーメッセージが入るので、if @task.errors.any?の条件に当てはまり、errorsが取得できるかな、と思ったら、「undefined method `errors' for nil:NilClass」のエラーが出てしまいます。これは@taskがnilになってしまっているのだと思います。

###ソースコード

rails

1<%= form_for [@project, @project.tasks.build] do |f| %> 2 <%= f.text_field :title %> 3 <% if @task.errors.any? %> #自分で追記した行 4 <%= @task.errors.messages[:title][0] %> #自分で追記した行 5 <% end %> #自分で追記した行 6 <%= f.submit %>

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

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

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

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

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

guest

回答2

0

失礼いたします。
私も同様の事で悩んでおります。

こちらの投稿を参考にさせていただき、修正をこころみたのですが、
projects/show.html.erb表示時に「undefined method `errors' for nil:NilClass」のエラーが消えません。

どこか誤りがあるのでしょうか?

project/show.html.erb <h1><%= @project.title %></h1> <ul> <% @project.tasks.each do |task| %> <li> <%= check_box_tag '', '', task.done, {'data-id' => task.id, 'data-project_id' => task.project_id} %> <%= task.title %> <%= link_to "[delete]", project_task_path(task.project_id, task.id), method: :delete, data: { confirm: "are you sure?" } %> </li> <% end %> <li> <%= form_for [@project, @project.tasks.build] do |f| %> <%= f.text_field :title %> <% if @task.errors.any? %> #追記行 ここでエラー <%= @task.errors.messages[:title][0] %> #追記行 <% end %> #追記行 <%= f.submit %> <% end %> </li> </ul> <script> $(function(){ $('input[type=checkbox]').click(function(){ var idProject = $(this).data('project_id'),idTask = $(this).data('id'); $.post('/projects/' + idProject + '/tasks/' + idTask + '/toggle'); }); }); </script>
class Task < ActiveRecord::Base belongs_to :project validates :title, presence: {message: "入力してください。"} scope :unfinished, -> { where(done: false) } end
class TasksController < ApplicationController # タスク登録 def create @project = Project.find(params[:project_id]) @task = @project.tasks.create(task_params) if!@task.new_record? logger.error("---------- こっち ----------") redirect_to project_path(@project.id) else logger.error("---------- どっち ----------") render 'projects/show' end private def task_params params[:task].permit(:title) end end

以上、ご鞭撻をいただけると幸いです。

投稿2015/10/30 13:25

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

nok2015

2015/10/30 14:22 編集

>kimusyunn様 じつは私もアドバイスを実践するだけだと同じように「undefined method `errors' for nil:NilClass」が表示されてしまったんですね。 私もまだ初心者なので認識があやしいのですが、このエラーは、「errorsというメソッドはnil(存在しない)の対象には使えませんよ」という意味なのだと思うんですね。じゃあerrorsメソッドの対象となっているオブジェクト(レシーバ)はどれか?というと、この場合@taskですよね。 なので、これはこのように読み替えることができるんです。「@taskがnil(存在しない)ですよ」と。 それで、ProjectsControllerを以下のように編集したところ、エラーが出なくなり、うまくいくようになりました。 ``` def show @task = Task.new end ``` redirect_to project_path(@project.id)でよばれるのはshowアクションなので、そのshowアクションの中で、@task = Task.newとしてやり、「@taskはTaskクラスのオブジェクトですよ」と定義してやることで、nilでなくしてやる、、というイメージでやっています(自信ありませんが、うまくいってます) 参考になれば幸いです。
nok2015

2015/10/30 23:16 編集

show.html.erbにこのように書くと、 ``` <%= @task.errors.messages[:title][0] unless @task.nil? %> ``` projects_controller.rbのshowアクションを書かなくてもうまく動きました。 これは「@taskがnilなら何もしない。@taskがnilではなかったら、@task.errors.messages[:title:[0]を表示する」という意味です。 tryメソッドを使うともっとスマートに書けるようなのですが、いま調べているところです。
guest

0

ベストアンサー

おそらくTasksControllerでは

def create @project = Project.find(params[:project_id]) @task = @project.tasks.create(task_params) redirect_to project_path(@project.id) end

のようにredirectしかしていないのではないでしょうか。

ProjectsControllerでは

def create @project = Project.new(project_params) if @project.save redirect_to projects_path else render 'new' end end

のようにsaveが失敗したときはrender処理を書いていたのでエラーメッセージが表示できていました。

taskも同様にrender処理を書いてあげないとエラーメッセージが表示できないかと思います。

redirect_toはアクションが呼び直されてしまうので@taskごとエラーメッセージが消されてしまいますが、
renderはページを表示するだけなのでエラーメッセージが消えずに表示できます。

redirect_to でメッセージを表示する際は、flash[:notice]にメッセージを渡してあげれば表示できますが
たぶん特殊なやりかただと思いますのでrenderでいいと思います。

【追記2015.10.30】

def create @project = Project.find(params[:project_id]) @task = @project.tasks.create(task_params) if !@task.new_record? # binding.pry redirect_to project_path(@project.id) else # binding.pry render 'projects/show' end end

このように

if !@task.new_record? #新しいレコードでないか? か if @task.persisted? #保存済みか?

でcreateの結果を調べてあげる必要があります。(saveメソッドの時は失敗するとfalseが戻ります)
ActiveRecordの更新系操作

if @task = @project.tasks.create(task_params)

では未入力チェックがかかってもFalseにはならないので面倒ですが上記処理で行っていただけますでしょうか。
よろしくお願いします。

投稿2015/10/28 10:37

編集2015/10/29 21:27
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

nok2015

2015/10/29 11:42

コメントありがとうございます。 TasksControllerには以下のように記述しています。 ``` def create @project = Project.find(params[:project_id]) if @task = @project.tasks.create(task_params) redirect_to project_path(@project.id) else render 'show' end end ``` それでもエラーメッセージが表示されません。 ターミナルを観察しながら空白登録してみると、どうやらvalidatesが効いて空白での登録はできないようになっているようなのですが、なぜかcreateアクションのif文がまったく無視されて、elseのほうへ進まないようなのです。。。 renderとredirect_toには違いがあるのですね。勉強になりました。 flashメッセージを使ってのエラーメッセージ表示もできませんでした。 どう書いても、if文のelse以降に進まず、なぜかリダイレクトしてしまうのです。 どうしたものでしょうか。。。
nok2015

2015/10/29 23:20

【2015.10.30追記】 ありがとうございます。アドバイス通りに書いてみたところ、無事エラーメッセージが表示できました。本当にうれしいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問