【发布时间】:2019-03-07 09:51:25
【问题描述】:
我正在尝试重新创建类似于 app.stackoverflow 的堆栈溢出。一个用户提出问题,其他人可以回答。我在问题页面上有一个缩进的嵌套表单,以便从其他用户那里获得答案。
在发布答案后我很难检索数据,并且我在更新操作的问题控制器页面上错误地设置了@answer,我无法弄清楚如何正确检索此变量鉴于来自 questions_controller 的参数没有单独设置答案的详细信息。如何检索与@answer 相关的参数部分,以便我可以设置变量,或者我可能需要为此使用不同的路由?
我的表单如下所示:
<%= form_for @question do |form| %>
<%=form.fields_for :answer do |answer_form| %>
<div class="form-group">
<%=answer_form.text_area :answer_attributes, placeholder: "Add your answer", rows:10, class:"form-control" %>
<%=answer_form.hidden_field :user_id, value: current_user.id, class:'d-none' %>
<%=answer_form.hidden_field :question_id, value: @question.id %>
</div>
<% end %>
<div>
<%=form.submit 'Post Your Answer', class: 'btn-primary' %>
</div>
<% end %>
我的问题模型如下所示:
class Question < ApplicationRecord
has_many :answers, dependent: :destroy
belongs_to :user
accepts_nested_attributes_for :answers
validates :headline, presence: true , length: { minimum: 20 }
validates :body, presence: true, length: { minimum: 50 }
validates_associated :answers
end
答案模型是:
class Answer < ApplicationRecord
belongs_to :user
belongs_to :question
validates :body, presence: true, length: { minimum: 50 }
end
问题控制器:
class QuestionsController < ApplicationController
before_action :authenticate_user!, except: [:index, :show]
before_action :set_question, except: [:index, :new, :create]
def index
@questions = Question.all.order("id DESC")
end
def show
@question = Question.find(params[:id])
@user = User.find(@question.user_id)
@answers = @question.answers
@answer = Answer.new
end
def new
@question = Question.new
@question.answers.new
end
def create
@question = current_user.questions.new(question_params)
if @question.save
flash[:notice] = "You have successfully posted your question"
redirect_to @question
else
@errors = @question.errors.full_messages
render action: :new
end
end
def edit
set_question
@question = Question.find(params[:id])
end
def update
@question = Question.find(params[:id])
@question.update(question_params)
@answer = @question.answers.new(question_params)
@question.answers.first.user_id = current_user.id
if @question.save
flash[:notice] = "You have sucessfully posted your answer"
redirect_to @question
else
redirect_to new_question_answer_path(@answer), flash: { danger: @question.errors.full_messages.join(",")}
end
end
private
def set_question
@question = Question.find(params[:id])
end
def question_params
params.require(:question).permit(:headline, :body, :user_id, :answer, answers_attributes:[:body, :user_id, :question_id])
end
end
应答控制器:
class AnswersController < ApplicationController
before_action :find_question
def index
@answers = @question.answers
@user = User.find(@question.user_id)
end
def show
@answer = Answer.find(params[:id])
@user = User.find(@question.user_id)
end
def new
@answer = Answer.new(:question_id => @question.id)
end
def create
@answer = Answer.new(answer_params)
if @answer.save
flash[:notice] = "You have sucessfully created the answer."
redirect_to(answers_path(@answer, :question_id => @question.id))
else
flash[:alert] = "Failed to save the answer."
@errors = @answer.errors.full_messages
render :new
end
end
def edit
@answer = Answer.find(params[:id])
end
def update
@answer = Answer.find(params[:id])
if @answer.update_attributes(answer_params)
flash[:notice] = "You have sucessfully updated the answer."
redirect_to(answer_path(@answer, :question_id => @question.id))
else
render :edit
end
end
def delete
@answer = Asnwer.find(params[:id])
end
def destroy
@answer = Answer.find(params[:id])
@answer.destroy
flash[:notice] = "Answer was destroyed"
redirect_to(answers_path)
end
private
def answer_params
params.require(:answer).permit(:body, :user_id, :question_id)
end
def find_question
@question = Question.find(params[:question_id])
end
end
我的路线文件如下所示:
Rails.application.routes.draw do
get 'questions/index'
root to: 'questions#index'
resources :questions do
resources :answers
end
devise_for :users
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
更新:这里是从服务器启动和显示索引页面到我进入问题页面并记录答案的那一刻的日志
rails server
=> Booting Puma
=> Rails 5.2.2 application starting in development
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.12.0 (ruby 2.6.0-p0), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
Started GET "/questions/11/answers" for 127.0.0.1 at 2019-03-07 16:10:13 +0600
(1.4ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
↳ /Users/irina/.rvm/gems/ruby-2.6.0/gems/activerecord-5.2.2/lib/active_record/log_subscriber.rb:98
Processing by AnswersController#index as HTML
Parameters: {"question_id"=>"11"}
Question Load (0.8ms) SELECT "questions".* FROM "questions" WHERE "questions"."id" = $1 LIMIT $2 [["id", 11], ["LIMIT", 1]]
↳ app/controllers/answers_controller.rb:65
User Load (2.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 3], ["LIMIT", 1]]
↳ app/controllers/answers_controller.rb:6
Rendering answers/index.html.erb within layouts/application
Answer Load (0.9ms) SELECT "answers".* FROM "answers" WHERE "answers"."question_id" = $1 [["question_id", 11]]
↳ app/views/answers/index.html.erb:11
User Load (1.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 3], ["LIMIT", 1]]
↳ app/views/answers/_new.html.erb:7
Rendered answers/_new.html.erb (61.7ms)
Rendered answers/index.html.erb within layouts/application (92.7ms)
[Webpacker] Compiling…
Started GET "/questions/11/answers" for 127.0.0.1 at 2019-03-07 16:10:18 +0600
Processing by AnswersController#index as HTML
Parameters: {"question_id"=>"11"}
Question Load (1.4ms) SELECT "questions".* FROM "questions" WHERE "questions"."id" = $1 LIMIT $2 [["id", 11], ["LIMIT", 1]]
↳ app/controllers/answers_controller.rb:65
User Load (1.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 3], ["LIMIT", 1]]
↳ app/controllers/answers_controller.rb:6
Rendering answers/index.html.erb within layouts/application
Answer Load (1.3ms) SELECT "answers".* FROM "answers" WHERE "answers"."question_id" = $1 [["question_id", 11]]
↳ app/views/answers/index.html.erb:11
User Load (1.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 3], ["LIMIT", 1]]
↳ app/views/answers/_new.html.erb:7
Rendered answers/_new.html.erb (9.3ms)
Rendered answers/index.html.erb within layouts/application (18.5ms)
Completed 200 OK in 133ms (Views: 108.3ms | ActiveRecord: 18.4ms)
[Webpacker] Compilation failed:
Hash: 53a953077891e4cef2e8
Version: webpack 3.12.0
Time: 2928ms
Asset Size Chunks Chunk Names
application-c57a289721a93641de38.js 3.1 kB 0 [emitted] application
application-c57a289721a93641de38.js.map 2.49 kB 0 [emitted] application
manifest.json 142 bytes [emitted]
[0] ./app/javascript/packs/application.js 346 bytes {0} [built] [failed] [1 error]
ERROR in ./app/javascript/packs/application.js
Module build failed: SyntaxError: Unexpected token (14:15)
12 | if(window.railsEnv && window.railsEnv === 'development'){
13 | try {
> 14 | render(<App />, reactElement)
| ^
15 | } catch (e) {
16 | render(<RedBox error={e} />, reactElement)
17 | }
Completed 200 OK in 11715ms (Views: 11626.9ms | ActiveRecord: 27.7ms)
Started PATCH "/questions/11" for 127.0.0.1 at 2019-03-07 16:10:41 +0600
Processing by QuestionsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"q7HQt4uGPwBIIz0icswfJLWMRk6MiopIfWu9JBcjkuX1VpGBdwlwZu903NDuebSaX8Y90VHnvcEoaV8unV2zkw==", "question"=>{"answer"=>{"answer_attributes"=>"This is the test answer to see how the information goes through", "user_id"=>"3", "question_id"=>"11"}}, "commit"=>"Post Your Answer", "id"=>"11"}
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 3], ["LIMIT", 1]]
↳ /Users/irina/.rvm/gems/ruby-2.6.0/gems/activerecord-5.2.2/lib/active_record/log_subscriber.rb:98
Question Load (0.5ms) SELECT "questions".* FROM "questions" WHERE "questions"."id" = $1 LIMIT $2 [["id", 11], ["LIMIT", 1]]
↳ app/controllers/questions_controller.rb:55
CACHE Question Load (0.0ms) SELECT "questions".* FROM "questions" WHERE "questions"."id" = $1 LIMIT $2 [["id", 11], ["LIMIT", 1]]
↳ app/controllers/questions_controller.rb:39
Unpermitted parameter: :answer
(0.5ms) BEGIN
↳ app/controllers/questions_controller.rb:40
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 3], ["LIMIT", 1]]
↳ app/controllers/questions_controller.rb:40
Answer Load (0.5ms) SELECT "answers".* FROM "answers" WHERE "answers"."question_id" = $1 [["question_id", 11]]
↳ app/controllers/questions_controller.rb:40
(0.3ms) COMMIT
↳ app/controllers/questions_controller.rb:40
Unpermitted parameter: :answer
(0.3ms) BEGIN
↳ app/controllers/questions_controller.rb:44
CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 3], ["LIMIT", 1]]
↳ app/controllers/questions_controller.rb:44
(0.4ms) ROLLBACK
↳ app/controllers/questions_controller.rb:44
Completed 500 Internal Server Error in 97ms (ActiveRecord: 8.3ms)
ActionController::UrlGenerationError (No route matches {:action=>"new", :controller=>"answers", :question_id=>nil}, missing required keys: [:question_id]):
app/controllers/questions_controller.rb:48:in `update'
UPDATE NO 2。看起来由于这个错误设置了@answer,@question 没有按预期保存,并且条件踢的第二部分重定向到 new_question_answer_path。我尝试将其更新为 edit_question_answer_path 并且它给出了与没有路由匹配的相同错误。
如果我在 Pry 中打开答案,我会得到以下对象:
[1] pry(#<QuestionsController>)> @answer
=> #<Answer:0x00007fc3ec823c98
id: nil,
body: nil,
question_id: 11,
user_id: 3,
selected: nil,
created_at: nil,
updated_at: nil>
更新 3 看起来像将我的 routes.rb 更改为
Rails.application.routes.draw do
resources :questions, :has_many => :answers
root to: 'questions#index'
resources :questions do
resources :answers
end
devise_for :users
end
并更改此答案的形式
<h2> Your Answer </h2>
<%= form_for [@question, Answer.new] do |form| %>
<div class="form-group">
<%=form.text_area :body, placeholder: "Add your answer", rows:10, class:"form-control" %><br>
<%=form.hidden_field :user_id, value: current_user.id, class:'d-none' %>
<%=form.hidden_field :question_id, value: @question.id %>
</div>
<div>
<%=form.submit 'Post Your Answer', class: 'btn-primary' %>
</div>
<% end %>
成功了并帮助解决了问题。我不确定这是否是一个完美的解决方案)
【问题讨论】:
-
我们需要查看您的服务器日志以了解参数是如何传递的。点击提交后复制并粘贴服务器输出的任何内容
-
奇怪的是,您为问题构建了一个表单,而您只查询答案。为什么不只为先前存在的问题下方的答案构建一个表单。因为您已经将问题 ID 作为隐藏字段传递,所以您可以轻松地将答案与正确的问题相关联...... 一件小事:您将 Answer 设为 User 的子项,但您不需要将其作为答案已经是问题的孩子,它本身就是用户的孩子。您可以轻松找到给出任何答案的用户。
-
看起来像更新 route.rb 和编辑表单就可以了,并且应用程序正常工作。我以更新 NO 3 的形式将新的 route.rb 和 view/answers/_new.html.erb 添加到我的问题中。
-
这个视频看起来很有帮助railscasts.com/episodes/…
-
Maxence,感谢您让我朝着正确的方向思考我认为表格设置不正确。同时,该应用程序的结构期望有一个用户提出问题,而任何其他用户回答它,所以我看不出我将如何追溯用户 ID 以获得问题的答案。我没有在我的问题中澄清这一点是我的错。
标签: ruby-on-rails forms nested