RailsStore.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.data.RailsStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.data.RailsStore"] = true;
  8. dojo.provide("dojox.data.RailsStore");
  9. dojo.require("dojox.data.JsonRestStore");
  10. // Contains code donated by Travis Tilley under CLA
  11. dojo.declare("dojox.data.RailsStore", dojox.data.JsonRestStore, {
  12. constructor: function(){
  13. // summary:
  14. // RailsStore is a data store for interacting with RESTful Rails controllers
  15. },
  16. preamble: function(options){
  17. if(typeof options.target == 'string' && !options.service){
  18. var target = options.target.replace(/\/$/g, '');
  19. // Special getRequest handler for handling content type negotiation via
  20. // the Rails format extension, as well as properly setting the ID param
  21. // in the URL.
  22. var getRequest = function(id, args){
  23. args = args || {};
  24. var url = target;
  25. var query;
  26. var ident;
  27. if(dojo.isObject(id)){
  28. ident = '';
  29. query = '?' + dojo.objectToQuery(id);
  30. }else if(args.queryStr && args.queryStr.indexOf('?') != -1){
  31. ident = args.queryStr.replace(/\?.*/, '');
  32. query = args.queryStr.replace(/[^?]*\?/g, '?');
  33. }else if(dojo.isString(args.query) && args.query.indexOf('?') != -1){
  34. ident = args.query.replace(/\?.*/, '');
  35. query = args.query.replace(/[^?]*\?/g, '?');
  36. }else{
  37. ident = id ? id.toString() : '';
  38. query = '';
  39. }
  40. if(ident.indexOf('=') != -1){
  41. query = ident;
  42. ident = '';
  43. }
  44. if(ident){
  45. url = url + '/' + ident + '.json' + query;
  46. }else{
  47. url = url + '.json' + query;
  48. }
  49. var isSync = dojox.rpc._sync;
  50. dojox.rpc._sync = false;
  51. return {
  52. url : url,
  53. handleAs : 'json',
  54. contentType : 'application/json',
  55. sync : isSync,
  56. headers : {
  57. Accept : 'application/json,application/javascript',
  58. Range : args && (args.start >= 0 || args.count >= 0)
  59. ? "items="
  60. + (args.start || '0')
  61. + '-'
  62. + ((args.count && (args.count
  63. + (args.start || 0) - 1)) || '')
  64. : undefined
  65. }
  66. };
  67. };
  68. options.service = dojox.rpc.Rest(this.target, true, null,
  69. getRequest);
  70. }
  71. },
  72. fetch: function(args){
  73. args = args || {};
  74. function addToQueryStr(obj){
  75. function buildInitialQueryString(){
  76. if(args.queryStr == null){
  77. args.queryStr = '';
  78. }
  79. if(dojo.isObject(args.query)){
  80. args.queryStr = '?' + dojo.objectToQuery(args.query);
  81. }else if(dojo.isString(args.query)){
  82. args.queryStr = args.query;
  83. }
  84. }
  85. function separator(){
  86. if(args.queryStr.indexOf('?') == -1){
  87. return '?';
  88. }else{
  89. return '&';
  90. }
  91. }
  92. if(args.queryStr == null){
  93. buildInitialQueryString();
  94. }
  95. args.queryStr = args.queryStr + separator() + dojo.objectToQuery(obj);
  96. }
  97. if(args.start || args.count){
  98. // in addition to the content range headers, also provide query parameters for use
  99. // with the will_paginate plugin if so desired.
  100. if((args.start || 0) % args.count){
  101. throw new Error("The start parameter must be a multiple of the count parameter");
  102. }
  103. addToQueryStr({
  104. page: ((args.start || 0) / args.count) + 1,
  105. per_page: args.count
  106. });
  107. }
  108. if(args.sort){
  109. // make the sort into query parameters
  110. var queryObj = {
  111. sortBy : [],
  112. sortDir : []
  113. };
  114. dojo.forEach(args.sort, function(item){
  115. queryObj.sortBy.push(item.attribute);
  116. queryObj.sortDir.push(!!item.descending ? 'DESC' : 'ASC');
  117. });
  118. addToQueryStr(queryObj);
  119. delete args.sort;
  120. }
  121. return this.inherited(arguments);
  122. },
  123. _processResults: function(results, deferred){
  124. var items;
  125. /*
  126. * depending on the ActiveRecord::Base.include_root_in_json setting,
  127. * you might get back an array of attribute objects, or an array of
  128. * objects with the attribute object nested under an attribute having
  129. * the same name as the (remote and unguessable) model class.
  130. *
  131. * 'Example' without root_in_json: [{'id':1, 'text':'first'}]
  132. * 'Example' with root_in_json: [{'example':{'id':1, 'text':'first'}}]
  133. */
  134. if((typeof this.rootAttribute == 'undefined') && results[0]){
  135. if(results[0][this.idAttribute]){
  136. this.rootAttribute = false;
  137. console.debug('RailsStore: without root_in_json');
  138. }else{
  139. for(var attribute in results[0]){
  140. if(results[0][attribute][this.idAttribute]){
  141. this.rootAttribute = attribute;
  142. console.debug('RailsStore: with root_in_json, attribute: ' + attribute);
  143. }
  144. }
  145. }
  146. }
  147. if(this.rootAttribute){
  148. items = dojo.map(results, function(item){
  149. return item[this.rootAttribute];
  150. }, this);
  151. }else{
  152. items = results;
  153. }
  154. // index the results
  155. var count = results.length;
  156. // if we don't know the length, and it is partial result, we will guess that it is twice as big, that will work for most widgets
  157. return {totalCount:deferred.fullLength || (deferred.request.count == count ? (deferred.request.start || 0) + count * 2 : count), items: items};
  158. }
  159. });
  160. }