问题描述
我有一个Rails API,我试图将一个数字数组传递给我的postgres db,但是我不能:我发送一个带有两个值的数组,并且它接受一个只有第一个值的数组。
我有2个模型,Itinary
和Event
,其中:
class Event
belongs_to: itinary
accepts_nested_attributes_for :itinary
class Itinary
has_many: events
我在Postgres中使用Postgres和React前端以及Rails API。我用array
类型的值声明了decimal
类型的列:
- Rails Postgres模式:我将
DECIMAL
设置为类型:
create_table "itinaries",force: :cascade do |t|
...
t.decimal "start_gps",default: [],array: true
def event_params
params.require(:event).permit(
...,itinary_attributes: [...,start_gps: [] ],...
)
end
我检查了Event.first.itinary.start_gps.class
返回Array
。我可以使用Itinary.create!(...,start_gps:[45,1])
(值是数字)进行播种。
- 反应形式:数据是在React的
FormData
中发送的,我相信我使用了正确的Rails命名约定:
const fdata = new FormData()
fdata.append("events[itinary_attributes][start]",itinary.start)
fdata.append("events[itinary_attributes][start_gps][]",itinary.start_gps)
...
所以我的POST请求的标头包含:
event[itinary_attributes][start_gps][]: 45.1936513315257,0.6646728515625
在提交时,我几乎得到了所需的参数,但是引用了数组中的值:
Parameters:
{"event"=>{
"itinary_attributes"=>{
"date"=>"2020-08-16","start"=>"Paris FRA","start_gps"=>["48.85011347181819,2.3353889957070355"],<< one value ?
}
}
}
以便在Postgres触发时我只获得第一个值:
Itinary Create (2.5ms)
INSERT INTO "itinaries" ...
["start_gps","{48.85011347181819}"],<<<<< ONLY FirsT
^^
]
- 如果我在架构中将
t.string
或t.text
设置为数据类型,则Postgres将触发:
Itinary Create (2.5ms)
["start_gps","{\"45.18978009667531,0.6811523437500001\"}"]]
所以Event.last.itinary.start_gps.length
返回1,一个连接值:
start_gps: Array(1)
=> "45.158800738352106,1.5051269531250002"
我什至试图从React提交一个字符串数组,但是没有成功。从哪儿开始?我相信这是非常经典的。看起来Rails或Postgres无法读取逗号“,”,该逗号将数组中的两个值分开。
解决方法
您可能想尝试一下:
const fdata = new FormData()
fdata.append("events[itinary_attributes][start]",itinary.start)
fdata.append("events[itinary_attributes][start_gps][]",itinary.start_gps[0])
fdata.append("events[itinary_attributes][start_gps][]",itinary.start_gps[1])
这应该让你
{"event"=>{
"itinary_attributes"=>{
"date"=>"2020-08-16","start"=>"Paris FRA","start_gps"=>["48.85011347181819","2.3353889957070355"] <-- Two values in an array
}
,
如果有兴趣,可以“手动”解决:将数字数组保存到数组字段中,我将接收到的参数拆分。这是不令人满意的,因为这样简单的工作需要很多手势。我仍然看不到有什么问题。
一种解决方案是添加控制器:
if params[:event][:itinary_attributes][:start_gps]
params[:event][:itinary_attributes][:start_gps] = params[:event][:itinary_attributes][:start_gps][0].split(',')
end
event_params = params.require(:event).permit(
...,itinary_attributes: [...,:start,start_gps: [],end_gps: []],)
Event.new(event_params)
...