回答編集履歴

3

回答を追記しました

2021/02/27 09:04

投稿

jnchito
jnchito

スコア357

answer CHANGED
@@ -53,4 +53,83 @@
53
53
  post project_tasks_url(@project), headers: headers, params: { task: new_task }
54
54
  ```
55
55
 
56
- 以上、参考になれば幸いです。
56
+ 以上、参考になれば幸いです。
57
+
58
+ ## コメントを受けての追記
59
+
60
+ > それが`project_tasks/url(@project)`にしているのですが、上記のようなエラーが出てしまいます。
61
+ > 該当のコードのURLは以下のようになります
62
+ > https://github.com/YouheiNozaki/Everyday-rails-v6/blob/main/spec/requests/tasks_request_spec.rb
63
+
64
+ コードの共有ありがとうございます!これだと手元でもエラーを再現できるので非常に助かります。
65
+ というわけで、僕もローカルで再現させてみました。
66
+
67
+ これ、前回のコメントですっかり見落としていましたが、RSpec側のパスではなく、Viewに書かれたパスの間違いですね。
68
+ しかも、ryusouさんの間違いではなくオリジナルのサンプルコードの間違いです。(Oh...????)
69
+
70
+ [https://github.com/everydayrails/everydayrails-rspec-2017/blob/90b22535d44ab626b82363335a227c5a1856a039/app/views/tasks/_task.json.jbuilder#L2](https://github.com/everydayrails/everydayrails-rspec-2017/blob/90b22535d44ab626b82363335a227c5a1856a039/app/views/tasks/_task.json.jbuilder#L2)
71
+
72
+ 正しくはこうですね。
73
+
74
+ ```diff
75
+ -json.url project_task_url([task.project, task], format: :json)
76
+ +json.url project_task_url(task.project, task, format: :json)
77
+ ```
78
+
79
+ こうすればテストはパスするはずです。
80
+
81
+ ### コントローラースペックでエラーが起きなかった理由
82
+
83
+ ではなぜViewに不具合があったのにコントローラースペックの方はパスしたのでしょうか?
84
+ これはコントローラースペックはデフォルトでViewをレンダリングしないためです。
85
+ そのため、コントローラースペックという名前の通り「コントローラーは異常なし!だからヨシ!(Viewは知らん!)」となってしまったわけです。
86
+
87
+ ただし、`render_views`というメソッドを呼びだしておくと、コントローラースペックでもViewのレンダリングを強制することができます。
88
+ こうするとコントローラースペックでもエラーが発生するようになります。
89
+
90
+ ```diff
91
+ require 'rails_helper'
92
+
93
+ RSpec.describe TasksController, type: :controller do
94
+ + render_views
95
+ include_context "project setup"
96
+ ```
97
+
98
+ 実行結果
99
+
100
+ ```
101
+ Failures:
102
+
103
+ 1) TasksController#create responds with JSON formatted output
104
+ Failure/Error: json.url project_task_url([task.project, task], format: :json)
105
+
106
+ ActionView::Template::Error:
107
+ No route matches {:action=>"show", :controller=>"tasks", :format=>:json, :project_id=>[#<Project id: 1, name: "Project 2", description: "A test project.", due_on: "2021-03-06", created_at: "2021-02-27 07:53:57.565109000 +0000", updated_at: "2021-02-27 07:53:57.565109000 +0000", user_id: 1, completed: nil>, #<Task id: 1, name: "New test task", project_id: 1, completed: nil, created_at: "2021-02-27 07:53:57.574235000 +0000", updated_at: "2021-02-27 07:53:57.574235000 +0000">]}, missing required keys: [:id]
108
+ Did you mean? project_tasks_url
109
+ project_task_path
110
+ project_tasks_path
111
+ new_project_task_url
112
+ # ./app/views/tasks/_task.json.jbuilder:2:in `_app_views_tasks__task_json_jbuilder___3745737086157069224_66100'
113
+ # ./app/views/tasks/show.json.jbuilder:1:in `_app_views_tasks_show_json_jbuilder__4444021816594691676_66060'
114
+ # ./app/controllers/tasks_controller.rb:34:in `block (2 levels) in create'
115
+ # ./app/controllers/tasks_controller.rb:31:in `create'
116
+ # ./spec/controllers/tasks_controller_spec.rb:20:in `block (3 levels) in <top (required)>'
117
+ # ------------------
118
+ # --- Caused by: ---
119
+ # ActionController::UrlGenerationError:
120
+ # No route matches {:action=>"show", :controller=>"tasks", :format=>:json, :project_id=>[#<Project id: 1, name: "Project 2", description: "A test project.", due_on: "2021-03-06", created_at: "2021-02-27 07:53:57.565109000 +0000", updated_at: "2021-02-27 07:53:57.565109000 +0000", user_id: 1, completed: nil>, #<Task id: 1, name: "New test task", project_id: 1, completed: nil, created_at: "2021-02-27 07:53:57.574235000 +0000", updated_at: "2021-02-27 07:53:57.574235000 +0000">]}, missing required keys: [:id]
121
+ # Did you mean? project_tasks_url
122
+ # project_task_path
123
+ # project_tasks_path
124
+ # new_project_task_url
125
+ # ./app/views/tasks/_task.json.jbuilder:2:in `_app_views_tasks__task_json_jbuilder___3745737086157069224_66100'
126
+ ```
127
+
128
+ `rails s`で起動したサンプルアプリケーションではTaskの作成はJSONではなくHTMLリクエストで実行されることもあり、JSONレスポンスに不具合が隠れていることを検知できていませんでした。どうもすみません????‍♂️
129
+
130
+ というわけで、この件は原著者のAaronさんにフィードバックしておきました。
131
+
132
+ [\_task.json.jbuilder has invalid arguments for project\_task\_url · Issue \#112 · everydayrails/everydayrails\-rspec\-2017](https://github.com/everydayrails/everydayrails-rspec-2017/issues/112)
133
+
134
+ おかげさまで長年誰も気づいていなかった不具合を見つけることができました。
135
+ どうもありがとうございました!!

2

post先のURLを修正

2021/02/27 09:04

投稿

jnchito
jnchito

スコア357

answer CHANGED
@@ -50,7 +50,7 @@
50
50
  ここまで来れば答えはもうお分かりかと思いますが、正しくは`projects_url`ではなく、`tasks_url`を指定することです。ただ、この場合は単純に`projects_url`を置き換えるだけでなく、次のように書く必要があるかもしれません。(動作未確認)
51
51
 
52
52
  ```ruby
53
- post tasks_url(@project), headers: headers, params: { task: new_task }
53
+ post project_tasks_url(@project), headers: headers, params: { task: new_task }
54
54
  ```
55
55
 
56
56
  以上、参考になれば幸いです。

1

changed URL

2021/02/27 07:24

投稿

jnchito
jnchito

スコア357

answer CHANGED
@@ -45,7 +45,7 @@
45
45
 
46
46
  実際、エラーメッセージに表示されている `Failure/Error: params.require(:project).permit(:name, :description, :due_on)` は、ProjectsController内のコードです。
47
47
 
48
- https://github.com/JunichiIto/everydayrails-rspec-2017/blob/63e38f87c8edfdfb5861fa628429651f62c8492e/app/controllers/projects_controller.rb#L83
48
+ [https://github.com/everydayrails/everydayrails-rspec-2017/blob/63e38f87c8edfdfb5861fa628429651f62c8492e/app/controllers/projects_controller.rb#L83](https://github.com/everydayrails/everydayrails-rspec-2017/blob/63e38f87c8edfdfb5861fa628429651f62c8492e/app/controllers/projects_controller.rb#L83)
49
49
 
50
50
  ここまで来れば答えはもうお分かりかと思いますが、正しくは`projects_url`ではなく、`tasks_url`を指定することです。ただ、この場合は単純に`projects_url`を置き換えるだけでなく、次のように書く必要があるかもしれません。(動作未確認)
51
51