问题描述
我正在尝试使用来自 React 前端的 formData 进行一个 API 调用,该前端具有多个图像以及字符串/布尔值等,以更新实体
我正在使用主动存储,并且能够将多个图像附加到实体,但是当我想通过一个 API 调用(理想情况下)使用字符串等更新实体时。它是这样说的:
参数缺失或值为空:属性
我知道原因是我的 formData 的结构是这样的:
data: {"title": "xxxxxx","description": "xxxxxx" etc.},images[]: File,images[]: File etc.
而且我需要属性作为键而不是数据:
def property_params
params.require(:property).permit(:title,:description,:max_guests,:price_per_day,:address,:average_rating,:has_beach_nearby,:has_beds,:has_kitchen,:has_swimming_pool,:has_hdtv,:has_bathtub,:images [])
end
但是当我不这样做时,图像无法识别,因为这是不允许的,因此 API 不会接收它
我正在附上这样的图像(并且有效):
if params[:images].present?
params[:images].each do |image|
@property.images.attach(image)
end
end
是否可以使用一次 API 调用上传多张图片和数据?如果没有,我需要做什么?
这是整个属性控制器:
class Api::V1::PropertiesController < ApiController
before_action :authenticate_user!,only: [:update,:create,:destroy]
def index
@properties = Property.all
render json: @properties
end
def show
@property = Property.find(params[:id])
render json: @property
end
def update
@property = Property.find(params[:id])
if current_user === @property.user
if params[:images].present?
params[:images].each do |image|
@property.images.attach(image)
end
end
@property.update(property_params)
render json: {
success: "Successfully updated",property: @property},status: 200
else
render json: {
error: "You are not authorized to update this property"},status: 403
end
end
private
def property_params
params.require(:property).permit(:title,:images [])
end
被卡住了一段时间,所以非常感谢任何帮助(Rails 新手)
解决方法
Rack 使用方括号在 formdata 中传递哈希值:
irb(main):005:0> Rack::Utils.parse_nested_query("property[title]=foo&property[description]=bar")
=> {"property"=>{"title"=>"foo","description"=>"bar"}}
可以使用空括号传递数组:
irb(main):008:0> Rack::Utils.parse_nested_query("property[foo][]=a&property[foo]&[]=property[foo][]=c")
=> {"property"=>{"foo"=>nil}}
对于多部分表单数据,您通常会使用表单(可见表单或虚拟表单)并在输入上设置 name 属性:
<form action="/properties" method="post" multipart>
<input name="property[images][]" type="file" />
<input name="property[images][]" type="file" />
</form>
Rack 会将请求正文的各个部分拼接在一起并创建单个参数哈希。
您也有语法错误:
# Use sensible line lengths and this won't happen as often...
params.require(:property)
.permit(
:title,:description,:max_guests,:price_per_day,:address,:average_rating,:has_beach_nearby,:has_beds,:has_kitchen,:has_swimming_pool,:has_hdtv,:has_bathtub,images: []
)
要将数组或嵌套参数列入白名单,您需要使用哈希作为要允许的最后一个参数。 images: []
将允许包含 ActionDispatch::UploadedFile
的允许标量数组。
如果您想将包含嵌套和平面参数的非常规参数列入白名单,您需要更有创意。要记住的关键是 ActionController::Parameters
是一个类似散列的对象,您可以像散列一样操作它:
def property_params
params.require(:data)
.permit(
:title,:has_bathtub
).merge(
# fetch is like require but does not raise if the key is not present
images: params.fetch(:images,[])
)
end
使用 ActiveStorage,您实际上不会need to manually attach the files。
,我似乎通过这样做解决了它:
def update
@property = Property.find(params[:id])
if current_user === @property.user
if params[:images]
@property.images.attach(params[:images])
end
property = @property.update(property_params)
if property
render json: {
success: "Successfully updated",property: @property,images: @property.images
},status: 200
else
render json: {
error: "Error when updating this property",},status: 500
end
else
render json: {
error: "You are not authorized to update this property"
},status: 403
end
end
private
def property_params
json = JSON.parse(params[:data])
json = ActionController::Parameters.new(json)
json.permit(
:title,images: []
)
end
不确定这是否正确,但似乎有效