ruby-on-rails - XHR 表单提交到渲染部分被触发,但视图未更新
问题描述
我想我错过了一些明显的东西。
应该发生什么:
当用户将图像添加到 Story#new 表单时:
- 用户点击部分
file_field
中的Story#new
_form
: - Javascript
file_field
使用 XMLHttpRequest 将表单数据(包括包含图像)发布到自定义控制器操作 - 该自定义操作使用 ActiveStorage 将该图像附加到关联的报告
- 该自定义操作调用
.js.erb
重新呈现部分视图的视图 - 重新渲染的部分显示了附加的图像
实际发生了什么
除了#5之外的一切。
设置:
- 导轨 6
- 主动存储
- 哈姆尔
- 咖啡脚本
有问题的型号:
class Story < ApplicationRecord
belongs_to :report, inverse_of: :story
has_one_attached :image, dependent: :purge
def picture
image.attached? ? Rails.application.routes.url_helpers.rails_blob_path(image, only_path: true) :
ActionController::Base.helpers.asset_path('story_no_image.png')
end
end
class Report < ApplicationRecord
has_one :story, inverse_of: :report, dependent: :destroy
has_one_attached :image, dependent: :purge
def picture
image.attached? ? Rails.application.routes.url_helpers.rails_blob_path(image, only_path: true) :
ActionController::Base.helpers.asset_path('story_no_image.png')
end
end
故事是根据现有报告创建的。因此,为了“急切地预览”用户想要与故事相关联的图像,让我们暂时将其保存到相关报告中。
脚步:
1.用户点击部分file_field
中的Story#new
_form
:
# app/views/stories/_form.haml
# @story is new, but it's associated @report already exists,
# so let's temporarily associate the image with @report until @story gets created.
.container
.col-12
%h1 New Story
%h4= "For Report ##{link_to(@report.id, @report)} #{@report.details}".html_safe
.col-12
= simple_form_for @story, wrapper: :horizontal_form, html: { id: 'story_form' } do |f|
= f.input :report_id #, as: :hidden
.field
= f.input :title
.field.wysiwyg
= f.input :text, input_html: { class: "tinymce", style: "height: 300px;" }
.field
= f.label @story.image.present? ? 'Replace Picture:' : 'Choose Picture:'
= f.file_field :image, id: "image_upload", accept: 'image/*'
.actions
= f.submit 'Save', class: 'btn yellow'
.row.mt-5
.col-12
%h5 Image Preview:
.col-6#image_preview_wrapper
= render partial: 'image_preview', locals: { record: @story }
.col-6.text-center
=link_to 'Rotate Left', '#', class: 'rotate-btn', data: { rotation: 'left' }
=link_to 'Rotate Right', '#', class: 'rotate-btn', data: { rotation: 'right' }
=link_to 'Delete Image', '#', id: 'purge_img_btn'
= tinymce
# app/views/stories/_image_preview.haml
- byebug if record.class.name == 'Report' # using this debugger to make sure item #4 is actually happening
=image_tag(record.picture, id: "image_preview", class: 'yay!')
2. Javascript POST 表单数据
$(document).on 'turbolinks:load', ->
# only for new records:
if controllerMatches(['stories']) and actionMatches(['new', 'create'])
$('#image_upload').on 'change', ->
return unless !!$('#image_upload').val().length
reportId = $('#story_report_id').val()
eagerUrl = '/reports/' + reportId + '/upload_eager'
form = document.getElementById('story_form')
formData = new FormData(form)
xhr = new XMLHttpRequest()
xhr.open 'post', eagerUrl, true
xhr.send(formData)
自定义路由:
# routes.rb
resources :reports do
post 'upload_eager', on: :member
post 'rotate_eager', on: :member
end
3. 该自定义操作使用 ActiveStorage 将该图像附加到关联的报告
# ReportsController
def upload_eager
# for Story#new, upload an 'eager' image by attaching the image
# to the report (which exists) instead of the story (which doesn't)
authorize @report = Report.find(params[:id])
return unless eager_image_params[:image].present?
# this method is my customization of @report.image.attach(image_io)
# so I can rename and resize the image before uploading.
@report.upload_image!(eager_image_params[:image]) unless @report.image.attached?
respond_to do |format|
format.js
end
end
4. 该自定义操作调用.js.erb
重新呈现部分的视图:
# upload_eager.js.erb
$('#image_preview_wrapper').html("<%= j render partial: 'stories/image_preview', locals: { record: @report } %>");
$('#image_preview').removeClass('boo');
$('#image_preview').addClass('YAY');
5. 重新渲染的部分不显示附加的图像。
DOM 没有改变(注意我在 js 部分改变了标签的类)
- 我可以在 Chrome DevTools 中验证 #1 和 #2 正在发生(加上在
ReportsController#upload_eager
. - 我看到 #3 和 #4 发生在终端日志中(也使用调试器和控制台 gem)
- 我可以
byebug
在任何地方使用(调试器)并确认它工作正常,特别是@report
附有图像并且路径良好。
但是浏览器视图没有更新。
我唯一的成功是:如果我upload_eager
从 Network 事件中获取 JQuery 的结果,将其放入 DevTools 控制台并按 Enter 键,图像标签将被替换并且图像正确显示(又名 - JQuery 触发)。
这告诉我,来自部分的 JQuery 实际上并没有触发,我可以确认这一点,因为<img>
标签的类没有改变。
让我难过的是为什么终端日志显示部分已呈现:
Started POST "/reports/1615/upload_eager" for ::1 at 2019-11-21 23:09:16 -0500
Processing by ReportsController#upload_eager as */*
Parameters: {"utf8"=>"✓", "authenticity_token"=>"H2SVzwB8b02wNde/YePpYnVGBYa3nd6i4THa21MLOQbNQ/CgE/lIjAqpqaCUnsCKzEEZCDuEGuLfylWwwreo9g==", "story"=>{"report_id"=>"1615", "title"=>"", "prominent"=>"0", "text"=>"", "image"=>#<ActionDispatch::Http::UploadedFile:0x00007fc2237425b0 @tempfile=#<Tempfile:/var/folders/th/fsmws2ns6t54j_yy1wbk7qhc0000gn/T/RackMultipart20191121-80561-1j4sec1.JPG>, @original_filename="test-story-family-sam3.JPG", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"story[image]\"; filename=\"test-story-family-sam3.JPG\"\r\nContent-Type: image/jpeg\r\n">}, "year"=>"2019", "month"=>"8", "id"=>"1615"}
Report Load (0.3ms) SELECT "reports".* FROM "reports" WHERE "reports"."id" = $1 LIMIT $2 [["id", 1615], ["LIMIT", 1]]
↳ app/controllers/reports_controller.rb:82:in `upload_eager'
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/controllers/reports_controller.rb:82:in `upload_eager'
Unpermitted parameters: :report_id, :title, :prominent, :text
ActiveStorage::Attachment Load (0.4ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = $1 AND "active_storage_attachments"."record_type" = $2 AND "active_storage_attachments"."name" = $3 LIMIT $4 [["record_id", 1615], ["record_type", "Report"], ["name", "image"], ["LIMIT", 1]]
↳ app/controllers/reports_controller.rb:86:in `upload_eager'
Unpermitted parameters: :report_id, :title, :prominent, :text
(0.2ms) BEGIN
↳ app/models/report.rb:91:in `upload_image!'
Technology Load (0.4ms) SELECT "technologies".* FROM "technologies" WHERE "technologies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/models/report.rb:91:in `upload_image!'
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
↳ app/models/report.rb:91:in `upload_image!'
Contract Load (0.4ms) SELECT "contracts".* FROM "contracts" WHERE "contracts"."id" = $1 LIMIT $2 [["id", 4], ["LIMIT", 1]]
↳ app/models/report.rb:91:in `upload_image!'
Village Load (0.3ms) SELECT "villages".* FROM "villages" WHERE "villages"."id" = $1 LIMIT $2 [["id", 3], ["LIMIT", 1]]
↳ app/models/report.rb:91:in `upload_image!'
ActiveStorage::Blob Load (0.5ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" INNER JOIN "active_storage_attachments" ON "active_storage_blobs"."id" = "active_storage_attachments"."blob_id" WHERE "active_storage_attachments"."record_id" = $1 AND "active_storage_attachments"."record_type" = $2 AND "active_storage_attachments"."name" = $3 LIMIT $4 [["record_id", 1615], ["record_type", "Report"], ["name", "image"], ["LIMIT", 1]]
↳ app/models/report.rb:91:in `upload_image!'
ActiveStorage::Blob Create (0.4ms) INSERT INTO "active_storage_blobs" ("key", "filename", "content_type", "metadata", "byte_size", "checksum", "created_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["key", "moe206b5grl9laccxf4707kfb5ma"], ["filename", "000000_eager_1615.JPG"], ["content_type", "image/jpeg"], ["metadata", "{\"identified\":true}"], ["byte_size", 108855], ["checksum", "9BB+x9JRqJfEKb+RKcUEFA=="], ["created_at", "2019-11-22 04:09:17.443238"]]
↳ app/models/report.rb:91:in `upload_image!'
ActiveStorage::Attachment Create (0.4ms) INSERT INTO "active_storage_attachments" ("name", "record_type", "record_id", "blob_id", "created_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["name", "image"], ["record_type", "Report"], ["record_id", 1615], ["blob_id", 33], ["created_at", "2019-11-22 04:09:17.447089"]]
↳ app/models/report.rb:91:in `upload_image!'
(0.4ms) SELECT "plans"."id" FROM "plans" WHERE "plans"."contract_id" = $1 AND "plans"."technology_id" = $2 AND "plans"."planable_id" = $3 AND "plans"."planable_type" = $4 LIMIT $5 [["contract_id", 4], ["technology_id", 1], ["planable_id", 3], ["planable_type", "Village"], ["LIMIT", 1]]
↳ app/models/report.rb:274:in `find_plan'
Report Update (0.4ms) UPDATE "reports" SET "updated_at" = $1 WHERE "reports"."id" = $2 [["updated_at", "2019-11-22 04:09:17.450861"], ["id", 1615]]
↳ app/models/report.rb:91:in `upload_image!'
(0.6ms) COMMIT
↳ app/models/report.rb:91:in `upload_image!'
Disk Storage (5.8ms) Uploaded file to key: moe206b5grl9laccxf4707kfb5ma (checksum: 9BB+x9JRqJfEKb+RKcUEFA==)
Rendering reports/upload_eager.js.erb
Rendered stories/_image_preview.haml (Duration: 1.0ms | Allocations: 310)
Rendered reports/upload_eager.js.erb (Duration: 3.7ms | Allocations: 840)
Completed 200 OK in 1227ms (Views: 6.9ms | ActiveRecord: 5.5ms | Allocations: 20005)
解决方案
推荐阅读
- c# - 无法在 Visual Studio C# 上运行项目/文件
- php - 无法使用会话登录 codeigniter
- java - 使用带反射的安全管理器访问 jar 文件
- java - Uri 到位图然后转移另一个活动
- python - 计算移动平均线
- javascript - Javascript函数在复选框的onclick上不起作用
- openmp - 如何抑制 OMP 警告 #96 无法组建团队
- c++ - C ++“使用tcp = x”与“命名空间tcp = x”有什么区别
- airflow - 如何从脚本错误退出到 Airflow?
- vb.net - 在 Visual Basic 中使用 ArrayList.ToArray(Parameter?)