ruby-on-rails - Rails 6.1 在渲染时重定向到 json 页面
问题描述
我有一种情况,我正在使用频道发布评论,并且在将 rails 更新到 6.1 时,我遇到了一个奇怪的错误。创建方法如下所示
def create
offer = Offer.find(comment_params[:offer_id])
@comment = Comment.new(
user_id: current_user.id,
offer_id: offer.id,
content: comment_params[:content],
attachment_file: comment_params[:attachment_file]
)
if @comment.save
CommentChannel.broadcast_to offer, message: render_comment(@comment)
render json: { success: true }
else
render json: { success: true }
end
end
render_comment
方法如下
def render_comment(comment)
render_to_string(partial: "offers/comment", locals: {comment: comment}, layout: false)
end
这是按原样工作的,但现在每当我创建新评论时,它都会突然重定向到此页面
评论被创建,除了这个随机重定向之外,一切似乎都正常工作。这可能是什么原因?我以为它与render_to_string
,但无法弄清楚。
这里也是表格
<%= form_with model: Comment.new, id: 'new-comment' do |f| %>
<%= f.hidden_field :offer_id, value: @offer.id %>
<div>
<%= f.text_area :content %>
<div class="mt-3 flex items-center justify-between">
<%= f.submit "Comment", id:"comment-button",%>
</div>
<% end %>
解决方案
您看到的不是重定向。您正在发送一个非 XHR 请求,并且服务器正在返回呈现的 JSON 和一个application/json
内容类型。
您可以看到它触发了浏览器中的花哨 JSON 语法高亮和格式化。
你真正想要的东西是这样的:
# POST /offers/1/comments.json
def create
offer = Offer.find(params[:offer_id])
comment = offer.comments.new(comment_params) do |c|
c.user = current_user.id
end
if comment.save
CommentChannel.broadcast_to offer, message: render_comment(comment)
render json: comment,
status: :created,
location: comment
else
render json: { errors: comment.errors.full_messages },
status: :unprocessable_entity
end
end
# ...
private
def comment_params
params.require(:comment)
.permit(:content, :attachment_file)
end
这提供了一个更好的 API,您可以在集成测试中测试响应代码(您正在测试不是吗?;))而不是解析 JSON。
201 Created 响应不必在响应中包含实体,但它对于 ajax 获取新创建的对象非常有用。
您还应该嵌套路由而不是使用隐藏输入:
# routes.rb
resources :offers do
resources :comments, only: [:create]
end
<%= form_with model: [offer, comment],
id: 'new-comment',
"data-type" => 'json',
remote: true do |f| %>
<%= f.text_area :content %>
<div class="mt-3 flex items-center justify-between">
<%= f.submit "Comment", id:"comment-button",%>
</div>
<% end %>
由于 Rails 6.1form_with
没有默认设置,remote: true
因此您可以选择加入该config.action_view.form_with_generates_remote_forms
选项。Rails UJS 默认application/javascript
为 XHR 请求的类型。
由于您发送了正确的响应代码,它将触发适当的 ajax 处理程序方法:
let form = document.getElementById('new-comment');
// Handle when a comment is created
form.addEventListener("ajax:success", (event) => {
const [data, status, xhr] = event.detail;
console.log(data); // the newly created comment
});
// Handle invalid input
form.addEventListener("ajax:error", (event) => {
const [data, status, xhr] = event.detail;
console.log(data.errors); // the errors
});
推荐阅读
- regex - Notepad++ 仅返回 XML 标记中的内容
- go - 特定于模型的寄存器?
- swiftui - 使用 SwiftUI 时异步填充/预填充多个用户可变的“@State”值?
- reactjs - 在 ReactJS 组件中,当循环遍历 props 数组时,我只能使用循环的简写语法。为什么是这样?
- sql - 尝试通过记录表打印
- java - Jackson多态反序列化
- azure-devops - 在我的 Angular 2+ 源代码中从 MS DevOps 更新新 PAS 令牌的位置?
- java - 如何在 Spring Boot Tests 中设置 servlet 上下文路径?
- notepad++ - 在行的某个点处的两个反斜杠之间替换每行中的文本
- django - 我可以用 Django 渲染 VueJS 吗?