我正在做类似Reddit的简单网站。我正在尝试向报告帖子添加按钮。我使用report
创建了button_to
模型,我尝试将数据发布到report controller
来创建它,但是我收到了NoMethodError in ReportsController#create undefined method merge' for "post_id":String
model / report.rb
class Report < ApplicationRecord
belongs_to :reporting_user, class_name: 'Author'
has_one :post
end
report_controller.rb
class ReportsController < ApplicationController
def create
report = Report.new(report_params)
flash[:notice] = if report.save
'Raported'
else
report.errors.full_messages.join('. ')
end
end
def report_params
params.require(:post).merge(reporting_user: current_author.id)
end
end
和视图中的按钮
= button_to "Report", reports_path, method: :post, params: {post: post}
是什么原因导致了该问题?
编辑:
参数
=> <ActionController::Parameters {"authenticity_token"=>"sX0DQfM0rp97q8i16LGZfXPoSJNx15Hk4mmP35uFVh52bzVa30ei/Bxk/Bm40gnFmd2NvFEqj+Wze8ted66kig==", "post"=>"1", "controller"=>"reports", "action"=>"create"} permitted: false>
答案 0 :(得分:2)
首先,您要使用belongs_to
而不是has_one
。
class Report < ApplicationRecord
belongs_to :reporting_user, class_name: 'Author'
belongs_to :post
end
这样可以将post_id
外键列正确地放在reports
上。使用has_one
会将fk列放在posts
上,将不起作用。
通常最好的解决方案是制作报告a nested resource:
# /config/routes.rb
resources :posts do
resources :reports, only: [:create]
end
# app/controller/reports_controller.rb
class ReportsController
before_action :set_post
# POST /posts/:post_id/reports
def create
@report = @post.reports.new(reporting_user: current_author)
if @report.save
flash[:notice] = 'Reported'
else
flash[:notice] = report.errors.full_messages.join('. ')
end
redirect_to @post
end
private
def set_post
@post = Post.find(params[:post_id])
end
end
这使您可以将按钮简化为:
= button_to "Report", post_reports_path(post), method: :post
由于post_id
是路径的一部分,因此我们不需要发送任何其他参数。
如果您希望将来让用户通过表单传递其他信息,则通过传递一个块来创建/更新带有参数和会话数据的资源的更好方法是:
@report = @post.reports.new(report_params) do |r|
r.reporting_user = current_user
end
答案 1 :(得分:0)
ActionController::Parameters#require返回参数中所需键的值。通常这是一个从表单传回的对象。在this example中,require
将返回{name: "Francesco", age: 22, role: "admin"}
并进行合并。
您的视图正在发回Rails格式化为{post: 'string'}
的参数。我们将需要查看您的视图代码来确定到底需要更改什么。
更新:从发布的新代码中,我们可以看到发送回的参数是"post"=>"1"
。通常我们会期望post: {id: 1, ...}
。
更新:视图中的按钮将需要将params
键更新为类似 的内容编辑:我同意params: {post: {id: post.id}}
params: {report: { post_id: post}}
是更好的格式。
答案 2 :(得分:0)
问题似乎出在report_params
中。当您调用params.require(:post)
时,它将从params中获取:post->结果为字符串。您正在此字符串上调用merge
。
我建议更改视图:
= button_to "Report", reports_path, method: :post, params: { report: { post_id: post} }
然后在控制器中:
def report_params
params.require(:report).permit(:post_id).merge(reporting_user_id: current_author.id)
end
请注意,我还根据约定更改了命名:model_id用于表示模型,模型或模型本身的ID。