primaryobjects / contentblocks

Create simple editable CMS content blocks in node.js. Wrapper for Create.js CMS framework.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Rest service specifications

DerekDomino opened this issue · comments

Hello,

What is the format of the json documents returned by the REST api storing the block contents?

On the official demo, I tried by listening to data exchange between the frontend and the heroku server, but no block content data is exchanged (as far as I can see with the Chrome Developer Network Tools).

On the service I've set up, after having modified a block and hit the 'Save' button, ContentBlocks sends a GET to my REST service and then stops. I don't know what to return since this is the related collection in db is empty on service setup.

Doing a console.log(model.toJSON()) before the GET 200 in client-side contentblock.js provides a hint

{
 @subject: "<MyContentBlock>",
 @type: "<http://www.w3.org/2002/07/owl#Thing>",
 <http://viejs.org/ns/content>: "lmkmlkmm"
} 

(BTW MongoDB requires keys belonging to [A-Za-z$_])

My questions are:

  • Does the DB needs to be prepopulated with related block entries?
  • What is the expected format/content of these entries?
  • Format hinted does not look at this stage compatible with JSON/MongoDB, is a transformation required?

The DB doesn't need to be pre-populated. The documents will simply be created if they do not yet exist, when a new content block is seen in the page.

You have the correct format for the json. The service simply writes the json as-is to the db. You'll just need to implement service methods:

pathFind: web service path to Find method, example: '/v1/nest/find?q={"@subject":"[id]"}'
pathPost: web service path to Insert (POST) method, example: '/v1/nest'
pathPut: web service path to Update (PUT) method, example: '/v1/nest/[id]'
pathDelete: web service path to Delete (DELETE) method, example: '/v1/nest/[id]'

In the above examples, [id] is a placeholder for the Id variable that the library sends.

The keys are compatible with mongo (at least the version I'm using at mongolab). I haven't had any issues with this. The key names actually come from the Create.js system and I left them intact for compatibility. This way the code simply reads and writes the json exactly as-is.

For an example of the REST service that I use in the demo, see https://github.com/primaryobjects/redant/blob/master/routes/nest/index.js

In the example code, you can see how each REST method is implemented to simply read and write the json as-is. The id parameter is used to locate the record (for updates and deletes). Feel free to use that code as a starting template for your own service.

Also, you can setup the routes for the above code with the following (from https://github.com/primaryobjects/redant/blob/master/app.js)

app.get('/collection/find', nest.find);
app.post('/collection', nest.insert);
app.put('/collection/:itemId', nest.update);
app.delete('/collection/:itemId', nest.delete);

I have indeed a pretty similar REST API (backed by mongoose). The notable difference was that a "null" response was sent back to the client instead of 404 status response. Now fixed.

When hitting the save button, a single GET is issued (a 404 is returned) then nothing else happens (no POSTing of block contents):

GET /restcb/%3CMyContentBlock%3E?callback=jQuery111006249560113064945_1400597212160&_=1400597212162

Moreover, the 'Save' button stays in an intermediate state 'Saving'; no message at the browser console level.

The client javascript first does a GET to locate the content block. If data.length == 0, then it creates a new entry instead (see the Backbone.sync code in https://github.com/primaryobjects/contentblocks/blob/master/scripts/contentblocks.js).

Could you check if your response in the GET (find) method returns an empty array? The response should be [] if no records are found. Example from the demo service:
http://red-ant.herokuapp.com/v1/nest/find?q={"name":"nonexistingcontent"}

I'm wondering if your find method might be returning a json object in its response with something like a message "{"status": "not found"}, rather than an empty array. In this case, it would try to do an update, but get a javascript error when it doesn't find an _id property.

Returning an empty array does not work.

After inspecting contentblocks source, a 'jsonp' document/script is expected in
https://github.com/primaryobjects/contentblocks/blob/master/scripts/contentblocks.js#L84

By changing it to 'json' and returning an empty array, the success callback is triggered and a POST is sent. Note that returning a 404 for the Find method makes the error callback of $.ajax to be called instead of success'.

Now, another problem. The POST is sent to the wrong url. It seems the configuration of contentblocks in node is not reflected at the client level. The data is posted to

/create

while contentblocks is configured with:

// ContentBlocks
var contentBlocks = require('contentblocks')({
    app: keystone,
    host: hostname,
    pathFind: '/restcb/[id]',
    pathPost: '/restcb',
    pathPut: '/restcb/[id]',
    pathDelete: '/restcb/[id]'
});

In scripts/contentblocks.js there are several mentions of '/create' that should be replaced by the restUrl variable or by restUrl.replace('[id]', data[0]._id).

About the jsonp part, the demo web service includes a config line to enable jsonp. Maybe this was missing for your service, which would explain why changing to plain json resolved that issue?:

app.configure(function() {
   // ...
   app.set('jsonp callback', true);
}

See https://github.com/primaryobjects/redant/blob/master/app.js#L19

For the second issue, /create in the client javascript actually maps to the internal contentblocks controller https://github.com/primaryobjects/contentblocks/blob/master/lib/managers/ControllerManager.js. This shouldn't need to be changed. The controller, in turn, then calls your web service using the configured post, put, delete paths that you specified in the require() config line.

The only changes that "should" be needed, are the require() config lines to specify the paths to post, put, delete, and the url to the find method in the client javascript file. I think :)