2
votes

I have been trying to have my front end send a JSON object with a set of data to my database. Using Postgres, there is a special migration that handles JSON as 'payload':

class CreateTournois < ActiveRecord::Migration[5.1]
  def change
    create_table :tournois do |t|
      t.json 'payload'
      t.timestamps
    end
  end
end

Using xmlhttp, I submit my JSON to the model:

function save() {
  var tojs = myDiagram.model.toJSON();
  var json = JSON.stringify(tojs);

  var formData = new FormData();
  formData.append('payload', json);

  var request = new XMLHttpRequest();
  request.open("post", "http://localhost:3000/malesingle", "application/json", true);
  request.send(formData);
}

And I use a basic form tag:

<%= form_for Tournoi.new do |f| %>
  <button id="SaveButton" onclick="save()">Save</button>
<% end %>

My controller is where I seem to have some issues:

 def create
   if @tournoi.nil?
     @tournoi = Tournoi.new(payload: JSON.parse(params['payload']))
     @tournoi.save
     redirect_to  malesingle_url
   else
     redirect_to root_url
   end
 end

The content of my JSON object is inserted into the model and the change is saved into the data, but I get redirected to an error page even with the change being made.

I get this error on line 8 @tournoi = Tournoi.new(payload: JSON.parse(params['payload'])).:

TypeError no implicit conversion of nil into String

How can I get the params accepted by my controller? I don't know if its relevant but i'm using GoJs Library for this here are the line where myDiagram is initialized :

    var $ = go.GraphObject.make;  
  myDiagram =
    $(go.Diagram, "myDiagramDiv",        {
        initialContentAlignment: go.Spot.Center,  // center the content
        "textEditingTool.starting": go.TextEditingTool.SingleClick,
        "textEditingTool.textValidation": isValidScore,
        layout: $(go.TreeLayout, { angle: 180 }),
        "undoManager.isEnabled": true
      });

  // validation function for editing text
  function isValidScore(textblock, oldstr, newstr) {
    if (newstr === "") return true;
    var num = parseInt(newstr, 10);
    return !isNaN(num) && num >= 0 && num <= 1;
  }
3
Have you tried breaking that up a bit? ``` payload = JSON.parse(params['payload']) @tournoi = Tournoi.new(payload: payload) ``` Or inspected params['payload'] to ensure it's getting the right data? My guess is parsing the JSON is what is causing issues and there's some nil value somewhere it doesn't like. Possibly even params['payload']. Maybe similar question: stackoverflow.com/questions/40038922/…supremebeing7

3 Answers

2
votes

If that can be of any help, I solved a similar issue by using .to_json like this

JSON.parse(params.to_json)

0
votes

params['payload'] is nil. JSON.parse(...) throws this error if it's passed a nil value.

You could use the following to ensure the payload exists (if it's acceptable for there not to be a payload):

if @tournoi.nil? && params['payload']
  @tournoi = Tournoi.new(payload: JSON.parse(params['payload']))
  ...

Otherwise, it will be a case of fixing the Javascript as that's not currently passing the payload as it should be. Perhaps add where myDiagram is defined and you'll be able to get a little more help on this as needed :)

Let me know if you've any questions.

0
votes

An error is always raised when using @tournoi = Tournoi.new(payload: JSON.parse(params[:payload])), The TypeError is raised specifically on JSON.parse(params[:payload]), by just modifying the method create :

def create
      if @tournoi = Tournoi.new(payload: params['payload'])
          @tournoi.save
.......

Not parsing the params will save the payload but it will save another tournoi that has a payload nil, all i need to do is add a validation in my model to avoid a tournoi that has a nil payload to be saved :

class Tournoi < ApplicationRecord
  validates :payload, presence: true, allow_nil: false

When submitting into tournoi model the payload is inserted and commit, the db rollback on the second tournoi since the payload is nill