在 Rails 6 活动存储中更新记录时不要清除图像
Do Not purge image when updating record in Rails 6 Active Storage
我已经研究这个问题几天了,似乎找不到解决方案。
我有一个 Rails 6 的模型,用于 has_one_attached :image
的柱
用户可以创建新栏并附加图像。这很好用。
当用户编辑酒吧名称等酒吧信息并提交该信息时,默认情况下 Active Storage 会清除最初上传的图片,即使没有提交新图片也是如此。
在编辑过程中,如果用户没有提交新图片,而只是更改了记录,例如酒吧名称,我如何防止 Active Storage 自动清除图片?我想保留与 Bar 记录关联的图像。
我已经在我的模型中尝试 dependent: :purge_later
但没有成功。我也尝试过提交没有图像参数的参数 if bar_info.image.attached?
我的模型bar_info.rb
class BarInfo < ApplicationRecord
belongs_to :user
has_many :bar_specials, dependent: :destroy
has_one_attached :image
validates :user_id, presence: true
validates :barname, presence: true, length: { maximum: 100 }
validates :city, presence: true, length: { maximum: 50 }
validates :state, presence: true, length: { maximum: 50 }
validates :image, content_type: { in: %w[image/jpeg image/gif image/png],
message: "must be a valid image format" },
size: { less_than: 5.megabytes,
message: "should be less than 5MB" }
end
我的控制器bar_infos_controller.rb
class BarInfosController < ApplicationController
def update
@bar_info = BarInfo.find(params[:id])
@bar_info.user_id = current_user.id
@bar_info.image.attach(params[:bar_info][:image])
if @bar_info.update(bar_info_params)
flash[:notice] = "Bar Info Updated!"
redirect_to bar_info_path(@bar_info)
else
render "edit"
end
end
private
def bar_info_params
attributes = [ :barname, :city, :state, :image ]
params.require(:bar_info).permit(attributes)
end
end
我的编辑视图_form.html.erb
<div class="row">
<div class="col-md 6">
<%= form_with(model: @bar_info, local: true) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label "Bar Name (required)" %>
<%= f.text_area :barname, placeholder: "Bar name here", class: "form-control", size: "70x1" %>
<%= f.label "City (required)" %>
<%= f.text_area :city, placeholder: "San Diego", class: "form-control", size: "70x1" %>
<%= f.label "State (required)" %>
<%= f.select :state, CS.states(:us), class: "form-control" %>
<span class="image">
<p>Upload an image of Bar here!</p>
<%= f.file_field :image, accept: "image/jpeg,image/gif,image/png" %>
</span>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
<script type="text/javascript">
$("#bar_info_image").bind("change", function() {
const size_in_megabytes = this.files[0].size/1024/1024;
if (size_in_megabytes > 5) {
alert("Maximum file size is 5MB. Please choose a smaller file.");
$("$bar_info_image").val("");
}
});
</script>
</div>
</div>
bar_infos 路线:
bar_infos GET /bar_infos(.:format) bar_infos#index
POST /bar_infos(.:format) bar_infos#create
new_bar_info GET /bar_infos/new(.:format) bar_infos#new
edit_bar_info GET /bar_infos/:id/edit(.:format) bar_infos#edit
bar_info GET /bar_infos/:id(.:format) bar_infos#show
PATCH /bar_infos/:id(.:format) bar_infos#update
PUT /bar_infos/:id(.:format) bar_infos#update
DELETE /bar_infos/:id(.:format) bar_infos#destroy
TL;DR 我想编辑酒吧的名称并仍然保留随它上传的原始图片。 Active Storage 当前会在更新时清除该映像。
谢谢。
这是因为您的 update
控制器操作中的这一行:
def update
...
@bar_info.image.attach(params[:bar_info][:image])
...
end
如果用户没有在编辑操作中填写图像,您会将图像设置为 nil
,这会从 activestorage 中删除文件。您应该将此更新完全保留在 ActiveRecords update
操作上。您在允许的参数中有图像,因此它应该可以正常工作:
def update
@bar_info = BarInfo.find(params[:id])
@bar_info.user_id = current_user.id
if @bar_info.update(bar_info_params)
flash[:notice] = "Bar Info Updated!"
redirect_to bar_info_path(@bar_info)
else
render "edit"
end
end
private
def bar_info_params
attributes = [ :barname, :city, :state, :image ]
params.require(:bar_info).permit(*attributes)
end
(而且我认为 permit 调用 params.require(:bar_info).permit(*attributes)
中应该有 *
)
我已经研究这个问题几天了,似乎找不到解决方案。
我有一个 Rails 6 的模型,用于 has_one_attached :image
用户可以创建新栏并附加图像。这很好用。
当用户编辑酒吧名称等酒吧信息并提交该信息时,默认情况下 Active Storage 会清除最初上传的图片,即使没有提交新图片也是如此。
在编辑过程中,如果用户没有提交新图片,而只是更改了记录,例如酒吧名称,我如何防止 Active Storage 自动清除图片?我想保留与 Bar 记录关联的图像。
我已经在我的模型中尝试 dependent: :purge_later
但没有成功。我也尝试过提交没有图像参数的参数 if bar_info.image.attached?
我的模型bar_info.rb
class BarInfo < ApplicationRecord
belongs_to :user
has_many :bar_specials, dependent: :destroy
has_one_attached :image
validates :user_id, presence: true
validates :barname, presence: true, length: { maximum: 100 }
validates :city, presence: true, length: { maximum: 50 }
validates :state, presence: true, length: { maximum: 50 }
validates :image, content_type: { in: %w[image/jpeg image/gif image/png],
message: "must be a valid image format" },
size: { less_than: 5.megabytes,
message: "should be less than 5MB" }
end
我的控制器bar_infos_controller.rb
class BarInfosController < ApplicationController
def update
@bar_info = BarInfo.find(params[:id])
@bar_info.user_id = current_user.id
@bar_info.image.attach(params[:bar_info][:image])
if @bar_info.update(bar_info_params)
flash[:notice] = "Bar Info Updated!"
redirect_to bar_info_path(@bar_info)
else
render "edit"
end
end
private
def bar_info_params
attributes = [ :barname, :city, :state, :image ]
params.require(:bar_info).permit(attributes)
end
end
我的编辑视图_form.html.erb
<div class="row">
<div class="col-md 6">
<%= form_with(model: @bar_info, local: true) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label "Bar Name (required)" %>
<%= f.text_area :barname, placeholder: "Bar name here", class: "form-control", size: "70x1" %>
<%= f.label "City (required)" %>
<%= f.text_area :city, placeholder: "San Diego", class: "form-control", size: "70x1" %>
<%= f.label "State (required)" %>
<%= f.select :state, CS.states(:us), class: "form-control" %>
<span class="image">
<p>Upload an image of Bar here!</p>
<%= f.file_field :image, accept: "image/jpeg,image/gif,image/png" %>
</span>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
<script type="text/javascript">
$("#bar_info_image").bind("change", function() {
const size_in_megabytes = this.files[0].size/1024/1024;
if (size_in_megabytes > 5) {
alert("Maximum file size is 5MB. Please choose a smaller file.");
$("$bar_info_image").val("");
}
});
</script>
</div>
</div>
bar_infos 路线:
bar_infos GET /bar_infos(.:format) bar_infos#index
POST /bar_infos(.:format) bar_infos#create
new_bar_info GET /bar_infos/new(.:format) bar_infos#new
edit_bar_info GET /bar_infos/:id/edit(.:format) bar_infos#edit
bar_info GET /bar_infos/:id(.:format) bar_infos#show
PATCH /bar_infos/:id(.:format) bar_infos#update
PUT /bar_infos/:id(.:format) bar_infos#update
DELETE /bar_infos/:id(.:format) bar_infos#destroy
TL;DR 我想编辑酒吧的名称并仍然保留随它上传的原始图片。 Active Storage 当前会在更新时清除该映像。
谢谢。
这是因为您的 update
控制器操作中的这一行:
def update
...
@bar_info.image.attach(params[:bar_info][:image])
...
end
如果用户没有在编辑操作中填写图像,您会将图像设置为 nil
,这会从 activestorage 中删除文件。您应该将此更新完全保留在 ActiveRecords update
操作上。您在允许的参数中有图像,因此它应该可以正常工作:
def update
@bar_info = BarInfo.find(params[:id])
@bar_info.user_id = current_user.id
if @bar_info.update(bar_info_params)
flash[:notice] = "Bar Info Updated!"
redirect_to bar_info_path(@bar_info)
else
render "edit"
end
end
private
def bar_info_params
attributes = [ :barname, :city, :state, :image ]
params.require(:bar_info).permit(*attributes)
end
(而且我认为 permit 调用 params.require(:bar_info).permit(*attributes)
中应该有 *
)