RailsStore.js 4.8 KB

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