简体   繁体   中英

Rails, submitting array to postgres

I have a Rails API and I am trying to pass an array of numbers to my postgres db but I can't: I send an array with two values, and it accepts an array with only the first value.

I have 2 models, Itinary and Event where:

class Event 
  belongs_to: itinary
  accepts_nested_attributes_for :itinary

class Itinary
   has_many: events

I use Postgres and a React front end and Rails API with Postgres. I declared a column of type array with values if type decimal :

  • Rails Postgres schema: I set DECIMAL as the type:
create_table "itinaries", force: :cascade do |t|
    ...
    t.decimal "start_gps", default: [], array: true
  • Rails EventsController : nothing fancy, from the Event controller, the create method is: Event.new(event_params) , and the strong params method is also rather simple:
def event_params
   params.require(:event).permit( 
      ...,
      itinary_attributes: [...,  start_gps: [] ],
      ...
   )
end

I checked that Event.first.itinary.start_gps.class returns Array . I can seed with Itinary.create.(..,: start_gps,[45,1]) (the values are numbers).

  • React form: the data are sent within a FormData from React where I believe I used the correct Rails naming convention:
const fdata = new FormData()
fdata.append("events[itinary_attributes][start]", itinary.start)
fdata.append("events[itinary_attributes][start_gps][]", itinary.start_gps)
...

so the header of my POST request contains:

event[itinary_attributes][start_gps][]: 45.1936513315257,0.6646728515625

On submit, I get almost the desired params but the values in the array are quoted:

 Parameters: 
{"event"=>{
   "itinary_attributes"=>{
       "date"=>"2020-08-16",
       "start"=>"Paris FRA",
       "start_gps"=>["48.85011347181819,2.3353889957070355"], << one value ?
       }
   }
}

so that I get only the first value when Postgres fires:

 Itinary Create (2.5ms)  
INSERT INTO "itinaries" ...
  ["start_gps", "{48.85011347181819}"], <<<<< ONLY FIRST
                   ^^
]
  • If I set t.string or t.text as the data-type in the schema, Postgres fires:
Itinary Create (2.5ms) 
 ["start_gps", "{\"45.18978009667531,0.6811523437500001\"}"]]

so Event.last.itinary.start_gps.length returns 1, a concatenated value:

start_gps: Array(1)
=> "45.158800738352106,1.5051269531250002"

I even tried to submit an array of strings from React without success. Where to start? This is something very classical I believe. Looks like Rails or Postgres can't read the comma ',' that separates two values in an array.

You might want to try this:

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])

This should get you

{"event"=>{
  "itinary_attributes"=>{
    "date"=>"2020-08-16",
    "start"=>"Paris FRA",
    "start_gps"=>["48.85011347181819", "2.3353889957070355"] <-- Two values in an array
   }

In case of any interest, one can solve this 'manually': to save an array of numbers into an array field, I split the received params. This is unsatisfactory as such a simple job demands so much gesticulation. I still don't see what's wrong.

One solution is to add in the controller:

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)
...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM