{"__v":0,"_id":"5591afb5342e980d006db041","initVersion":{"_id":"5570895fcc189a21001ab3c0","version":"2.0.0"},"project":"54344d89bfaa3d0800c4d7fa","tags":[],"user":{"_id":"54344d6cbfaa3d0800c4d7f7","username":"","name":"Jason Dobry"},"createdAt":"2015-06-29T20:51:01.415Z","changelog":[],"body":"This article was provided by [kaisersly](https://github.com/kaisersly).\n\n# The problem\nRails default response to an update is:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"head :no_content\",\n      \"language\": \"ruby\",\n      \"name\": \"the_problem.rb\"\n    }\n  ]\n}\n[/block]\nwhich is an empty response with a status code of 204 (NO CONTENT).\n\nEven if you write:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"def update\\n\\tif @resource.update(params)\\n\\t\\trender @resource, status: :ok\\n\\tend\\nend\",\n      \"language\": \"ruby\",\n      \"name\": \"more_problem.rb\"\n    }\n  ]\n}\n[/block]\nyou'll still get an empty response (HEAD) with a 204 status code.\n\nWhen you do a `DS.find('resource', id)`, js-data will send a PUT request. It will then receive a HEAD 204 response and will try to inject the payload in the cache. So it will perform something like:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"DS.inject('resource', JSON.parse('')) // the '' comes from the empty payload in the HEAD response\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\nand will throw an error (you can't inject an empty object).\n\n# The Rails solution\nThis stackoverflow [question](http://stackoverflow.com/questions/9953887/simple-respond-with-in-rails-that-avoids-204-from-put) provides the Rails way to change the response.\n\n# The js-data solution\n## Step 1 : disable the injection\nYou can disable the injection when you update a resource.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"Resource.update(1234, { foo: 'bar' }, { cacheResponse: false }).then(...);\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\nYou can disable it app wide:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var store = new JSData.DS({\\n  beforeUpdate: function (Resource, data, cb) {\\n    resource.cacheResponse = false;\\n    cb(null, data);\\n  }\\n});\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\nor resource wide:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var Resource = DS.defineResource({\\n  name: 'resource',\\n  beforeUpdate: function (Resource, data, cb) {\\n    resource.cacheResponse = false;\\n    cb(null, data);\\n  };\\n});\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\n\nIf you use Angular (app wide) :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"angular.module('myApp', ['js-data'])\\n  .config(function (DSProvider) {\\n    DSProvider.defaults.beforeUpdate = function (resource, data, cb) {\\n      resource.cacheResponse = false;\\n      cb(null, data);\\n    };\\n});\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\n## Step 2 : inject the resource manually\nYou just disabled the injection. If you stop here, this will happens:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var myResource = DS.get('resource', 1);\\n// { name: 'my resource', id: 1 }\\nmyResource.name = 'a new name'\\nmyResource.DSSave();\\n\\nmyResource = DS.get('resource', 1);\\n// still { name: 'my resource', id: 1 } because the updated resource wasn't injected\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\nYou have to inject the resource when the update is successful :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var myResource = DS.get('resource', 1);\\n// { name: 'my resource', id: 1 }\\nmyResource.name = 'a new name'\\nmyResource.DSSave().then(function (data) { // data, the payload of the response, is empty\\n  DS.inject('resource', myResource);\\n});\\n\\nmyResource = DS.get('resource', 1);\\n// { name: 'a new name', id: 1 }\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]","slug":"handling-rails-head-204-on-update","title":"Handling Rails HEAD 204 on update"}

Handling Rails HEAD 204 on update


This article was provided by [kaisersly](https://github.com/kaisersly). # The problem Rails default response to an update is: [block:code] { "codes": [ { "code": "head :no_content", "language": "ruby", "name": "the_problem.rb" } ] } [/block] which is an empty response with a status code of 204 (NO CONTENT). Even if you write: [block:code] { "codes": [ { "code": "def update\n\tif @resource.update(params)\n\t\trender @resource, status: :ok\n\tend\nend", "language": "ruby", "name": "more_problem.rb" } ] } [/block] you'll still get an empty response (HEAD) with a 204 status code. When you do a `DS.find('resource', id)`, js-data will send a PUT request. It will then receive a HEAD 204 response and will try to inject the payload in the cache. So it will perform something like: [block:code] { "codes": [ { "code": "DS.inject('resource', JSON.parse('')) // the '' comes from the empty payload in the HEAD response", "language": "javascript" } ] } [/block] and will throw an error (you can't inject an empty object). # The Rails solution This stackoverflow [question](http://stackoverflow.com/questions/9953887/simple-respond-with-in-rails-that-avoids-204-from-put) provides the Rails way to change the response. # The js-data solution ## Step 1 : disable the injection You can disable the injection when you update a resource. [block:code] { "codes": [ { "code": "Resource.update(1234, { foo: 'bar' }, { cacheResponse: false }).then(...);", "language": "javascript" } ] } [/block] You can disable it app wide: [block:code] { "codes": [ { "code": "var store = new JSData.DS({\n beforeUpdate: function (Resource, data, cb) {\n resource.cacheResponse = false;\n cb(null, data);\n }\n});", "language": "javascript" } ] } [/block] or resource wide: [block:code] { "codes": [ { "code": "var Resource = DS.defineResource({\n name: 'resource',\n beforeUpdate: function (Resource, data, cb) {\n resource.cacheResponse = false;\n cb(null, data);\n };\n});", "language": "javascript" } ] } [/block] If you use Angular (app wide) : [block:code] { "codes": [ { "code": "angular.module('myApp', ['js-data'])\n .config(function (DSProvider) {\n DSProvider.defaults.beforeUpdate = function (resource, data, cb) {\n resource.cacheResponse = false;\n cb(null, data);\n };\n});", "language": "javascript" } ] } [/block] ## Step 2 : inject the resource manually You just disabled the injection. If you stop here, this will happens: [block:code] { "codes": [ { "code": "var myResource = DS.get('resource', 1);\n// { name: 'my resource', id: 1 }\nmyResource.name = 'a new name'\nmyResource.DSSave();\n\nmyResource = DS.get('resource', 1);\n// still { name: 'my resource', id: 1 } because the updated resource wasn't injected", "language": "javascript" } ] } [/block] You have to inject the resource when the update is successful : [block:code] { "codes": [ { "code": "var myResource = DS.get('resource', 1);\n// { name: 'my resource', id: 1 }\nmyResource.name = 'a new name'\nmyResource.DSSave().then(function (data) { // data, the payload of the response, is empty\n DS.inject('resource', myResource);\n});\n\nmyResource = DS.get('resource', 1);\n// { name: 'a new name', id: 1 }", "language": "javascript" } ] } [/block]