slender_data 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (261) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/slender_data.coffee +14 -0
  3. data/app/assets/javascripts/slender_data/brest_loader.coffee +139 -0
  4. data/app/assets/javascripts/slender_data/cache.coffee +9 -24
  5. data/app/assets/javascripts/slender_data/entry_store.coffee +107 -0
  6. data/app/assets/javascripts/slender_data/loading_indicator.coffee +28 -0
  7. data/app/assets/javascripts/slender_data/loading_tracker.coffee +74 -0
  8. data/app/assets/javascripts/slender_data/parameterizable.coffee +50 -0
  9. data/app/assets/javascripts/slender_data/persistence_manager.coffee +114 -233
  10. data/app/assets/javascripts/slender_data/queries/base_query.coffee +32 -0
  11. data/app/assets/javascripts/slender_data/queries/multi_query.coffee +91 -0
  12. data/app/assets/javascripts/slender_data/queries/single_query.coffee +81 -0
  13. data/app/assets/javascripts/slender_data/query_cache.coffee +87 -0
  14. data/lib/slender_data/version.rb +1 -1
  15. data/spec/dummy/Rakefile +6 -0
  16. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  17. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  18. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  19. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  20. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  21. data/spec/dummy/bin/bundle +3 -0
  22. data/spec/dummy/bin/rails +4 -0
  23. data/spec/dummy/bin/rake +4 -0
  24. data/spec/dummy/config.ru +4 -0
  25. data/spec/dummy/config/application.rb +23 -0
  26. data/spec/dummy/config/boot.rb +5 -0
  27. data/spec/dummy/config/database.yml +25 -0
  28. data/spec/dummy/config/environment.rb +5 -0
  29. data/spec/dummy/config/environments/development.rb +31 -0
  30. data/spec/dummy/config/environments/production.rb +80 -0
  31. data/spec/dummy/config/environments/test.rb +36 -0
  32. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  33. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  34. data/spec/dummy/config/initializers/inflections.rb +16 -0
  35. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  36. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  37. data/spec/dummy/config/initializers/session_store.rb +3 -0
  38. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  39. data/spec/dummy/config/locales/en.yml +23 -0
  40. data/spec/dummy/config/routes.rb +4 -0
  41. data/spec/dummy/db/test.sqlite3 +0 -0
  42. data/spec/dummy/lib/tasks/tasks.rake +13 -0
  43. data/spec/dummy/log/development.log +349013 -0
  44. data/spec/dummy/log/test.log +883 -0
  45. data/spec/dummy/public/404.html +58 -0
  46. data/spec/dummy/public/422.html +58 -0
  47. data/spec/dummy/public/500.html +57 -0
  48. data/spec/dummy/public/favicon.ico +0 -0
  49. data/spec/dummy/spec/javascripts/brest_loader_spec.coffee +314 -0
  50. data/spec/dummy/spec/javascripts/cache_spec.coffee +93 -0
  51. data/spec/dummy/spec/javascripts/entry_store_spec.coffee +315 -0
  52. data/spec/dummy/spec/javascripts/jquery.js +6 -0
  53. data/spec/dummy/spec/javascripts/loading_tracker_spec.coffee +95 -0
  54. data/spec/dummy/spec/javascripts/parameterizable_spec.coffee +138 -0
  55. data/spec/dummy/spec/javascripts/persistence_manager_spec.coffee +659 -0
  56. data/spec/dummy/spec/javascripts/queries/base_query_spec.coffee +41 -0
  57. data/spec/dummy/spec/javascripts/queries/multi_query_spec.coffee +143 -0
  58. data/spec/dummy/spec/javascripts/queries/single_query_spec.coffee +112 -0
  59. data/spec/dummy/spec/javascripts/query_cache_spec.coffee +347 -0
  60. data/spec/dummy/spec/javascripts/sinon-chai.js +109 -0
  61. data/spec/dummy/spec/javascripts/sinon.js +4290 -0
  62. data/spec/dummy/spec/javascripts/spec_helper.coffee +23 -0
  63. data/spec/dummy/tmp/cache/assets/development/sprockets/02dabf70b4ae4a034f349ce89b4831d8 +0 -0
  64. data/spec/dummy/tmp/cache/assets/development/sprockets/031a6c2e3a4e952151301446bd3fc16d +0 -0
  65. data/spec/dummy/tmp/cache/assets/development/sprockets/0373c4e5507b3195c4ad15224d991609 +0 -0
  66. data/spec/dummy/tmp/cache/assets/development/sprockets/05175bd457a57c3ad73ab9a2c8696c9b +0 -0
  67. data/spec/dummy/tmp/cache/assets/development/sprockets/086e89c7529d5063e771b41793bfe311 +0 -0
  68. data/spec/dummy/tmp/cache/assets/development/sprockets/08b36042c3a4a79ebd9cee8ee1b88e6a +0 -0
  69. data/spec/dummy/tmp/cache/assets/development/sprockets/10513fd445754b59bd6001ea6ee727d9 +0 -0
  70. data/spec/dummy/tmp/cache/assets/development/sprockets/124f6816f926ae28ad20cc56425f3c91 +0 -0
  71. data/spec/dummy/tmp/cache/assets/development/sprockets/12ce2414098e368903aeb9923e275ef7 +0 -0
  72. data/spec/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  73. data/spec/dummy/tmp/cache/assets/development/sprockets/14eca89f8dccac139fd132de35d22628 +0 -0
  74. data/spec/dummy/tmp/cache/assets/development/sprockets/16c8b12ef6dcb486a7b771e43bbcc117 +0 -0
  75. data/spec/dummy/tmp/cache/assets/development/sprockets/19cdfaa89f900500a03507b86afe1231 +0 -0
  76. data/spec/dummy/tmp/cache/assets/development/sprockets/1b3a4d533a743ca2ccfbca0986613995 +0 -0
  77. data/spec/dummy/tmp/cache/assets/development/sprockets/1ca8c5b832302c6c94692d0875a59605 +0 -0
  78. data/spec/dummy/tmp/cache/assets/development/sprockets/2e2576241d2a4969c9277fe85851c92b +0 -0
  79. data/spec/dummy/tmp/cache/assets/development/sprockets/2ec1baba6d6dc634d091b3acf8127cf7 +0 -0
  80. data/spec/dummy/tmp/cache/assets/development/sprockets/2ff315acad8ceec317fd566d792df64f +0 -0
  81. data/spec/dummy/tmp/cache/assets/development/sprockets/311f68c1b9e342ebab4c92c8cb2b5e54 +0 -0
  82. data/spec/dummy/tmp/cache/assets/development/sprockets/324a5040c964d5e8d293564383c49b91 +0 -0
  83. data/spec/dummy/tmp/cache/assets/development/sprockets/3310b5a70d0b220782ab3e87642834e9 +0 -0
  84. data/spec/dummy/tmp/cache/assets/development/sprockets/33ea745e7aa9669831758b7d36db1cb4 +0 -0
  85. data/spec/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  86. data/spec/dummy/tmp/cache/assets/development/sprockets/3999afdceee7ca8dcf53757221c62d71 +0 -0
  87. data/spec/dummy/tmp/cache/assets/development/sprockets/3ba03b9f1aab60e78424f36e0e6cce6c +0 -0
  88. data/spec/dummy/tmp/cache/assets/development/sprockets/3e9a6ed890157d94f18b480f0079d8e1 +0 -0
  89. data/spec/dummy/tmp/cache/assets/development/sprockets/3ef50ccfe459d5c89ecc79a448586b49 +0 -0
  90. data/spec/dummy/tmp/cache/assets/development/sprockets/46c298dc2ff12ec748c70c017684fc28 +0 -0
  91. data/spec/dummy/tmp/cache/assets/development/sprockets/476318dd8109fbf173335456cabb4128 +0 -0
  92. data/spec/dummy/tmp/cache/assets/development/sprockets/5602ee157ea76a2f44a43739a83b1a6c +0 -0
  93. data/spec/dummy/tmp/cache/assets/development/sprockets/5b390f4782d6b77f5aec7ec56f3ad934 +0 -0
  94. data/spec/dummy/tmp/cache/assets/development/sprockets/5b5a66f4eefc591d284af6535ae474ea +0 -0
  95. data/spec/dummy/tmp/cache/assets/development/sprockets/5c41eeb2e98dc0833647e8547880435e +0 -0
  96. data/spec/dummy/tmp/cache/assets/development/sprockets/5cd2936d626662390288ab4c07ff3957 +0 -0
  97. data/spec/dummy/tmp/cache/assets/development/sprockets/5fd362891a204d492d9fa57ffee6e114 +0 -0
  98. data/spec/dummy/tmp/cache/assets/development/sprockets/643d60abdbcc813c95214920f12f09c3 +0 -0
  99. data/spec/dummy/tmp/cache/assets/development/sprockets/6591bc7545da5a2f5f7dee20b1f110a5 +0 -0
  100. data/spec/dummy/tmp/cache/assets/development/sprockets/6597f36181468ff92ba4284afe001181 +0 -0
  101. data/spec/dummy/tmp/cache/assets/development/sprockets/69b7946c418b75e7ba78f9fc73d3e9b9 +0 -0
  102. data/spec/dummy/tmp/cache/assets/development/sprockets/6c75b81de9afea82a6cbb56749157e3f +0 -0
  103. data/spec/dummy/tmp/cache/assets/development/sprockets/6e4bc63f9308eb5929a77f7607101af1 +0 -0
  104. data/spec/dummy/tmp/cache/assets/development/sprockets/6ee2243cf1cf415b6267b84dd7b8ba77 +0 -0
  105. data/spec/dummy/tmp/cache/assets/development/sprockets/6f8457b4ba418f572891745381a1e0f5 +0 -0
  106. data/spec/dummy/tmp/cache/assets/development/sprockets/6fd5544e52538b06ac40e5b387b020a5 +0 -0
  107. data/spec/dummy/tmp/cache/assets/development/sprockets/6fed8361766f5ae3cbf781986d6945b2 +0 -0
  108. data/spec/dummy/tmp/cache/assets/development/sprockets/70ffa648dbbe0f2431e7f9307b569354 +0 -0
  109. data/spec/dummy/tmp/cache/assets/development/sprockets/731f0bc492f775825f046d500938fc5a +0 -0
  110. data/spec/dummy/tmp/cache/assets/development/sprockets/76153dd2cc3d0c6e584080efb16e872a +0 -0
  111. data/spec/dummy/tmp/cache/assets/development/sprockets/76cd4393e7976d030f4623b8b6b372a0 +0 -0
  112. data/spec/dummy/tmp/cache/assets/development/sprockets/78d5dac5e2f907dd68813ed23a0fd4ac +0 -0
  113. data/spec/dummy/tmp/cache/assets/development/sprockets/7a400f93bfb71a1a11c59b9804adda6d +0 -0
  114. data/spec/dummy/tmp/cache/assets/development/sprockets/7abf5e8d9666225cb1d7881798dbd87a +0 -0
  115. data/spec/dummy/tmp/cache/assets/development/sprockets/7d6f1f3e48f6cc97a9bb4606f8c5a020 +0 -0
  116. data/spec/dummy/tmp/cache/assets/development/sprockets/814ca144649e7dec9e9158b3ec3460f1 +0 -0
  117. data/spec/dummy/tmp/cache/assets/development/sprockets/83de5b2d2c5d49f7737ae1f0316435ec +0 -0
  118. data/spec/dummy/tmp/cache/assets/development/sprockets/84c67faa73fdd082d4bd7f7712cb0499 +0 -0
  119. data/spec/dummy/tmp/cache/assets/development/sprockets/87a6ddc523ccbf2673750499bede3fc9 +0 -0
  120. data/spec/dummy/tmp/cache/assets/development/sprockets/8a90082fa76a7f37dd92a9b9a9b9f593 +0 -0
  121. data/spec/dummy/tmp/cache/assets/development/sprockets/8c5b622a33c6c034ecb4e78f131c5f73 +0 -0
  122. data/spec/dummy/tmp/cache/assets/development/sprockets/8c9851849e82bb9670e56f046df437f9 +0 -0
  123. data/spec/dummy/tmp/cache/assets/development/sprockets/8fc1455d3af69de5da04bf2a2a3f0b74 +0 -0
  124. data/spec/dummy/tmp/cache/assets/development/sprockets/96af98519e5badf206b77c3ecaf86d20 +0 -0
  125. data/spec/dummy/tmp/cache/assets/development/sprockets/98610661915880264fdb51c8f1a14141 +0 -0
  126. data/spec/dummy/tmp/cache/assets/development/sprockets/9a00753cdfb01f357dc39eeada77d0bc +0 -0
  127. data/spec/dummy/tmp/cache/assets/development/sprockets/9ad3db355e00d28ed3faed6dea5b1bff +0 -0
  128. data/spec/dummy/tmp/cache/assets/development/sprockets/9cbb3109d489692fd270c77ffa9d9559 +0 -0
  129. data/spec/dummy/tmp/cache/assets/development/sprockets/a22afac508f5adc12bf48d2f8333b8f7 +0 -0
  130. data/spec/dummy/tmp/cache/assets/development/sprockets/a49d020ee42c78bf7d22a21e8ee3b80f +0 -0
  131. data/spec/dummy/tmp/cache/assets/development/sprockets/a4f4f6c56c368263c0fbcf3f1542aa73 +0 -0
  132. data/spec/dummy/tmp/cache/assets/development/sprockets/a56b8266298c4171918ee403aa1c9e0f +0 -0
  133. data/spec/dummy/tmp/cache/assets/development/sprockets/a73a44bfca198fdf779532b644ec8af5 +0 -0
  134. data/spec/dummy/tmp/cache/assets/development/sprockets/aa4a22da44bd1b7dbdbb18f983d6c09b +0 -0
  135. data/spec/dummy/tmp/cache/assets/development/sprockets/ab0236bf3eac5cd30348c18efce8246b +0 -0
  136. data/spec/dummy/tmp/cache/assets/development/sprockets/abf215c8dc45135a91f4f993514c653f +0 -0
  137. data/spec/dummy/tmp/cache/assets/development/sprockets/ac1b8c30ad00cc489b7ec78bd6e2fc6c +0 -0
  138. data/spec/dummy/tmp/cache/assets/development/sprockets/ae8bd07980ad64ef8e9ac3fe38413c6d +0 -0
  139. data/spec/dummy/tmp/cache/assets/development/sprockets/b1950420978c68074fc6fd81d4320bc0 +0 -0
  140. data/spec/dummy/tmp/cache/assets/development/sprockets/b2d6aa1cb303474ebf3bfc571904ad23 +0 -0
  141. data/spec/dummy/tmp/cache/assets/development/sprockets/b59a10f85562b39fc7dd651965df9cab +0 -0
  142. data/spec/dummy/tmp/cache/assets/development/sprockets/b8d24bca037cf4b0a9e2979c11c8aea8 +0 -0
  143. data/spec/dummy/tmp/cache/assets/development/sprockets/bc2f15f88df08b4265c83133d6107680 +0 -0
  144. data/spec/dummy/tmp/cache/assets/development/sprockets/bd7ddfa86995ff5d259ea37e4a90c51c +0 -0
  145. data/spec/dummy/tmp/cache/assets/development/sprockets/c0515d57887926d6e28a0f87da31ee8e +0 -0
  146. data/spec/dummy/tmp/cache/assets/development/sprockets/c4820232e07d4e298e834c1011a72faa +0 -0
  147. data/spec/dummy/tmp/cache/assets/development/sprockets/c6babc078901541de3f4cb5cc2703bea +0 -0
  148. data/spec/dummy/tmp/cache/assets/development/sprockets/c9635dd5cbd79bdd9c58a89f6ea01595 +0 -0
  149. data/spec/dummy/tmp/cache/assets/development/sprockets/c9962abce37f5a56d5f05afe1edfe1b8 +0 -0
  150. data/spec/dummy/tmp/cache/assets/development/sprockets/cce1f28f0d1f5c2817e6eaf392bac615 +0 -0
  151. data/spec/dummy/tmp/cache/assets/development/sprockets/d37cae0bfdf135e6e71bcd0572bef329 +0 -0
  152. data/spec/dummy/tmp/cache/assets/development/sprockets/d4956056f6f35287a04295df6e52575d +0 -0
  153. data/spec/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  154. data/spec/dummy/tmp/cache/assets/development/sprockets/dc54acb6b8cd4b84b13f440d57db37b1 +0 -0
  155. data/spec/dummy/tmp/cache/assets/development/sprockets/dd51c50b2d8231175e8da83e8b057120 +0 -0
  156. data/spec/dummy/tmp/cache/assets/development/sprockets/dec2df59b57b3639f89847e50416c924 +0 -0
  157. data/spec/dummy/tmp/cache/assets/development/sprockets/df45b0abc2c323093874639ceb72c012 +0 -0
  158. data/spec/dummy/tmp/cache/assets/development/sprockets/e0393ec0ca968f0d4182c82802da79d5 +0 -0
  159. data/spec/dummy/tmp/cache/assets/development/sprockets/e43bfee690613c316a59f122315314e5 +0 -0
  160. data/spec/dummy/tmp/cache/assets/development/sprockets/ed1d892145be7053348b0ba28c27b427 +0 -0
  161. data/spec/dummy/tmp/cache/assets/development/sprockets/ef2b922f05692ba49eb1f68801786b8e +0 -0
  162. data/spec/dummy/tmp/cache/assets/development/sprockets/efec5fde178e0875317a0d380222545d +0 -0
  163. data/spec/dummy/tmp/cache/assets/development/sprockets/f01906d52258e56e92a230dc3e55805d +0 -0
  164. data/spec/dummy/tmp/cache/assets/development/sprockets/f1b4ffa23205a95782c5c5050359429f +0 -0
  165. data/spec/dummy/tmp/cache/assets/development/sprockets/f2080a87aa027245a444b1486dce7792 +0 -0
  166. data/spec/dummy/tmp/cache/assets/development/sprockets/f37842723e3572ba18f02519dab4ee77 +0 -0
  167. data/spec/dummy/tmp/cache/assets/development/sprockets/f72501aca20f34d765720253853e6105 +0 -0
  168. data/spec/dummy/tmp/cache/assets/development/sprockets/f74306735334107c5d17684f524b65cf +0 -0
  169. data/spec/dummy/tmp/cache/assets/development/sprockets/f89dc49f90e98b448540556861f0173e +0 -0
  170. data/spec/dummy/tmp/cache/assets/development/sprockets/feadb1611975b23f2647e1ac656ad90b +0 -0
  171. data/spec/dummy/tmp/cache/assets/development/sprockets/ff445b9646db9910af486791b285b112 +0 -0
  172. data/spec/dummy/tmp/cache/assets/development/sprockets/ffa1eaa25729d9d4cd7e2fd666868936 +0 -0
  173. data/spec/dummy/tmp/cache/assets/test/sprockets/02dabf70b4ae4a034f349ce89b4831d8 +0 -0
  174. data/spec/dummy/tmp/cache/assets/test/sprockets/031a6c2e3a4e952151301446bd3fc16d +0 -0
  175. data/spec/dummy/tmp/cache/assets/test/sprockets/0373c4e5507b3195c4ad15224d991609 +0 -0
  176. data/spec/dummy/tmp/cache/assets/test/sprockets/05175bd457a57c3ad73ab9a2c8696c9b +0 -0
  177. data/spec/dummy/tmp/cache/assets/test/sprockets/086e89c7529d5063e771b41793bfe311 +0 -0
  178. data/spec/dummy/tmp/cache/assets/test/sprockets/08b36042c3a4a79ebd9cee8ee1b88e6a +0 -0
  179. data/spec/dummy/tmp/cache/assets/test/sprockets/10513fd445754b59bd6001ea6ee727d9 +0 -0
  180. data/spec/dummy/tmp/cache/assets/test/sprockets/124f6816f926ae28ad20cc56425f3c91 +0 -0
  181. data/spec/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  182. data/spec/dummy/tmp/cache/assets/test/sprockets/14eca89f8dccac139fd132de35d22628 +0 -0
  183. data/spec/dummy/tmp/cache/assets/test/sprockets/16c8b12ef6dcb486a7b771e43bbcc117 +0 -0
  184. data/spec/dummy/tmp/cache/assets/test/sprockets/2b22662f42e9f485aafa6a333faaa256 +0 -0
  185. data/spec/dummy/tmp/cache/assets/test/sprockets/2e2576241d2a4969c9277fe85851c92b +0 -0
  186. data/spec/dummy/tmp/cache/assets/test/sprockets/2ec1baba6d6dc634d091b3acf8127cf7 +0 -0
  187. data/spec/dummy/tmp/cache/assets/test/sprockets/2ff315acad8ceec317fd566d792df64f +0 -0
  188. data/spec/dummy/tmp/cache/assets/test/sprockets/311f68c1b9e342ebab4c92c8cb2b5e54 +0 -0
  189. data/spec/dummy/tmp/cache/assets/test/sprockets/324a5040c964d5e8d293564383c49b91 +0 -0
  190. data/spec/dummy/tmp/cache/assets/test/sprockets/3310b5a70d0b220782ab3e87642834e9 +0 -0
  191. data/spec/dummy/tmp/cache/assets/test/sprockets/33ea745e7aa9669831758b7d36db1cb4 +0 -0
  192. data/spec/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  193. data/spec/dummy/tmp/cache/assets/test/sprockets/3999afdceee7ca8dcf53757221c62d71 +0 -0
  194. data/spec/dummy/tmp/cache/assets/test/sprockets/3e9a6ed890157d94f18b480f0079d8e1 +0 -0
  195. data/spec/dummy/tmp/cache/assets/test/sprockets/3ef50ccfe459d5c89ecc79a448586b49 +0 -0
  196. data/spec/dummy/tmp/cache/assets/test/sprockets/46c298dc2ff12ec748c70c017684fc28 +0 -0
  197. data/spec/dummy/tmp/cache/assets/test/sprockets/476318dd8109fbf173335456cabb4128 +0 -0
  198. data/spec/dummy/tmp/cache/assets/test/sprockets/5602ee157ea76a2f44a43739a83b1a6c +0 -0
  199. data/spec/dummy/tmp/cache/assets/test/sprockets/5b390f4782d6b77f5aec7ec56f3ad934 +0 -0
  200. data/spec/dummy/tmp/cache/assets/test/sprockets/5b5a66f4eefc591d284af6535ae474ea +0 -0
  201. data/spec/dummy/tmp/cache/assets/test/sprockets/5cd2936d626662390288ab4c07ff3957 +0 -0
  202. data/spec/dummy/tmp/cache/assets/test/sprockets/643d60abdbcc813c95214920f12f09c3 +0 -0
  203. data/spec/dummy/tmp/cache/assets/test/sprockets/6597f36181468ff92ba4284afe001181 +0 -0
  204. data/spec/dummy/tmp/cache/assets/test/sprockets/6c75b81de9afea82a6cbb56749157e3f +0 -0
  205. data/spec/dummy/tmp/cache/assets/test/sprockets/6e4bc63f9308eb5929a77f7607101af1 +0 -0
  206. data/spec/dummy/tmp/cache/assets/test/sprockets/6ee2243cf1cf415b6267b84dd7b8ba77 +0 -0
  207. data/spec/dummy/tmp/cache/assets/test/sprockets/6f8457b4ba418f572891745381a1e0f5 +0 -0
  208. data/spec/dummy/tmp/cache/assets/test/sprockets/6fd5544e52538b06ac40e5b387b020a5 +0 -0
  209. data/spec/dummy/tmp/cache/assets/test/sprockets/6fed8361766f5ae3cbf781986d6945b2 +0 -0
  210. data/spec/dummy/tmp/cache/assets/test/sprockets/70ffa648dbbe0f2431e7f9307b569354 +0 -0
  211. data/spec/dummy/tmp/cache/assets/test/sprockets/76cd4393e7976d030f4623b8b6b372a0 +0 -0
  212. data/spec/dummy/tmp/cache/assets/test/sprockets/7a400f93bfb71a1a11c59b9804adda6d +0 -0
  213. data/spec/dummy/tmp/cache/assets/test/sprockets/7abf5e8d9666225cb1d7881798dbd87a +0 -0
  214. data/spec/dummy/tmp/cache/assets/test/sprockets/7d6f1f3e48f6cc97a9bb4606f8c5a020 +0 -0
  215. data/spec/dummy/tmp/cache/assets/test/sprockets/814ca144649e7dec9e9158b3ec3460f1 +0 -0
  216. data/spec/dummy/tmp/cache/assets/test/sprockets/83de5b2d2c5d49f7737ae1f0316435ec +0 -0
  217. data/spec/dummy/tmp/cache/assets/test/sprockets/873c5252aa4eab7409b712c5e276bad2 +0 -0
  218. data/spec/dummy/tmp/cache/assets/test/sprockets/87a6ddc523ccbf2673750499bede3fc9 +0 -0
  219. data/spec/dummy/tmp/cache/assets/test/sprockets/8a90082fa76a7f37dd92a9b9a9b9f593 +0 -0
  220. data/spec/dummy/tmp/cache/assets/test/sprockets/8c5b622a33c6c034ecb4e78f131c5f73 +0 -0
  221. data/spec/dummy/tmp/cache/assets/test/sprockets/8c9851849e82bb9670e56f046df437f9 +0 -0
  222. data/spec/dummy/tmp/cache/assets/test/sprockets/8fc1455d3af69de5da04bf2a2a3f0b74 +0 -0
  223. data/spec/dummy/tmp/cache/assets/test/sprockets/98610661915880264fdb51c8f1a14141 +0 -0
  224. data/spec/dummy/tmp/cache/assets/test/sprockets/9a00753cdfb01f357dc39eeada77d0bc +0 -0
  225. data/spec/dummy/tmp/cache/assets/test/sprockets/9ad3db355e00d28ed3faed6dea5b1bff +0 -0
  226. data/spec/dummy/tmp/cache/assets/test/sprockets/a22afac508f5adc12bf48d2f8333b8f7 +0 -0
  227. data/spec/dummy/tmp/cache/assets/test/sprockets/a4f4f6c56c368263c0fbcf3f1542aa73 +0 -0
  228. data/spec/dummy/tmp/cache/assets/test/sprockets/a56b8266298c4171918ee403aa1c9e0f +0 -0
  229. data/spec/dummy/tmp/cache/assets/test/sprockets/a73a44bfca198fdf779532b644ec8af5 +0 -0
  230. data/spec/dummy/tmp/cache/assets/test/sprockets/aa4a22da44bd1b7dbdbb18f983d6c09b +0 -0
  231. data/spec/dummy/tmp/cache/assets/test/sprockets/ab0236bf3eac5cd30348c18efce8246b +0 -0
  232. data/spec/dummy/tmp/cache/assets/test/sprockets/ac1b8c30ad00cc489b7ec78bd6e2fc6c +0 -0
  233. data/spec/dummy/tmp/cache/assets/test/sprockets/ae8bd07980ad64ef8e9ac3fe38413c6d +0 -0
  234. data/spec/dummy/tmp/cache/assets/test/sprockets/b1950420978c68074fc6fd81d4320bc0 +0 -0
  235. data/spec/dummy/tmp/cache/assets/test/sprockets/b2d6aa1cb303474ebf3bfc571904ad23 +0 -0
  236. data/spec/dummy/tmp/cache/assets/test/sprockets/b8d24bca037cf4b0a9e2979c11c8aea8 +0 -0
  237. data/spec/dummy/tmp/cache/assets/test/sprockets/bc2f15f88df08b4265c83133d6107680 +0 -0
  238. data/spec/dummy/tmp/cache/assets/test/sprockets/c9962abce37f5a56d5f05afe1edfe1b8 +0 -0
  239. data/spec/dummy/tmp/cache/assets/test/sprockets/cce1f28f0d1f5c2817e6eaf392bac615 +0 -0
  240. data/spec/dummy/tmp/cache/assets/test/sprockets/d37cae0bfdf135e6e71bcd0572bef329 +0 -0
  241. data/spec/dummy/tmp/cache/assets/test/sprockets/d4956056f6f35287a04295df6e52575d +0 -0
  242. data/spec/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  243. data/spec/dummy/tmp/cache/assets/test/sprockets/dc54acb6b8cd4b84b13f440d57db37b1 +0 -0
  244. data/spec/dummy/tmp/cache/assets/test/sprockets/dd51c50b2d8231175e8da83e8b057120 +0 -0
  245. data/spec/dummy/tmp/cache/assets/test/sprockets/df13b2e8a88a9dcdc4a830fdd8f8d7b8 +0 -0
  246. data/spec/dummy/tmp/cache/assets/test/sprockets/df45b0abc2c323093874639ceb72c012 +0 -0
  247. data/spec/dummy/tmp/cache/assets/test/sprockets/e0393ec0ca968f0d4182c82802da79d5 +0 -0
  248. data/spec/dummy/tmp/cache/assets/test/sprockets/e43bfee690613c316a59f122315314e5 +0 -0
  249. data/spec/dummy/tmp/cache/assets/test/sprockets/ed1d892145be7053348b0ba28c27b427 +0 -0
  250. data/spec/dummy/tmp/cache/assets/test/sprockets/ef2b922f05692ba49eb1f68801786b8e +0 -0
  251. data/spec/dummy/tmp/cache/assets/test/sprockets/f01906d52258e56e92a230dc3e55805d +0 -0
  252. data/spec/dummy/tmp/cache/assets/test/sprockets/f1b4ffa23205a95782c5c5050359429f +0 -0
  253. data/spec/dummy/tmp/cache/assets/test/sprockets/f2080a87aa027245a444b1486dce7792 +0 -0
  254. data/spec/dummy/tmp/cache/assets/test/sprockets/f37842723e3572ba18f02519dab4ee77 +0 -0
  255. data/spec/dummy/tmp/cache/assets/test/sprockets/f72501aca20f34d765720253853e6105 +0 -0
  256. data/spec/dummy/tmp/cache/assets/test/sprockets/feadb1611975b23f2647e1ac656ad90b +0 -0
  257. data/spec/dummy/tmp/cache/assets/test/sprockets/ff445b9646db9910af486791b285b112 +0 -0
  258. metadata +499 -6
  259. data/app/assets/javascripts/slender_data.js +0 -8
  260. data/app/assets/javascripts/slender_data/ajax_loader.coffee +0 -76
  261. data/app/assets/javascripts/slender_data/indexed_cache.coffee +0 -33
@@ -0,0 +1,138 @@
1
+ #= require spec_helper
2
+
3
+
4
+ describe 'Parameterizable', ->
5
+
6
+ beforeEach ->
7
+ define_test_data this
8
+
9
+
10
+ describe 'constructor', ->
11
+
12
+ it 'stores the given parameters for later use', ->
13
+ @parameterizable = new slender_data.Parameterizable @test_params
14
+ expect(@parameterizable.params).to.not.be.undefined
15
+
16
+ it 'allows to configure the name of data models', ->
17
+ @parameterizable = new slender_data.Parameterizable @test_params
18
+ expect(@parameterizable.entry_name).to.equal 'user'
19
+
20
+ it 'defaults the name for a collection of data models to the plural version of the name of a single data model', ->
21
+ @parameterizable = new slender_data.Parameterizable @test_params
22
+ expect(@parameterizable.entries_name).to.equal 'users'
23
+
24
+ it 'allows to configure the name for a collection of data models', ->
25
+ @test_params.entries_name = 'humans'
26
+ @parameterizable = new slender_data.Parameterizable @test_params
27
+ expect(@parameterizable.entries_name).to.equal 'humans'
28
+
29
+ it 'uses the "id" attribute as an identifier by default', ->
30
+ @test_params.id_name = undefined
31
+ @parameterizable = new slender_data.Parameterizable @test_params
32
+ expect(@parameterizable.id_name).to.equal 'id'
33
+
34
+ it 'allows to configure which attribute is used as the indentifier', ->
35
+ @test_params.id_name = 'foo'
36
+ @parameterizable = new slender_data.Parameterizable @test_params
37
+ expect(@parameterizable.id_name).to.equal 'foo'
38
+
39
+ it 'defaults the name of a collection of identifiers to "ids"', ->
40
+ @test_params.id_name = undefined
41
+ @test_params.ids_name = undefined
42
+ @parameterizable = new slender_data.Parameterizable @test_params
43
+ expect(@parameterizable.ids_name).to.equal 'ids'
44
+
45
+ it 'allows to configure the name of a collection of identifiers', ->
46
+ @test_params.ids_name = 'foo'
47
+ @parameterizable = new slender_data.Parameterizable @test_params
48
+ expect(@parameterizable.ids_name).to.equal 'foo'
49
+
50
+ it 'uses the "version" attribute for versioning by default', ->
51
+ @test_params.version_name = undefined
52
+ @parameterizable = new slender_data.Parameterizable @test_params
53
+ expect(@parameterizable.version_name).to.equal 'version'
54
+
55
+ it 'allows to configure which attribute is used for versioning', ->
56
+ @test_params.version_name = 'foo'
57
+ @parameterizable = new slender_data.Parameterizable @test_params
58
+ expect(@parameterizable.version_name).to.equal 'foo'
59
+
60
+ it 'does not perform versioning by default', ->
61
+ @test_params.versioning = undefined
62
+ @parameterizable = new slender_data.Parameterizable @test_params
63
+ expect(@parameterizable.versioning).to.be.false
64
+
65
+ it 'allows to enable versioning', ->
66
+ @test_params.versioning = yes
67
+ @parameterizable = new slender_data.Parameterizable @test_params
68
+ expect(@parameterizable.versioning).to.be.true
69
+
70
+
71
+
72
+ describe 'querify_single', ->
73
+
74
+ beforeEach ->
75
+ @test_params.versioning = yes
76
+ @test_params.partial_entries = yes
77
+ @parameterizable = new slender_data.Parameterizable @test_params
78
+ @query_hash = id: 3, full: yes
79
+
80
+ context 'given a query hash', ->
81
+
82
+ beforeEach ->
83
+ @result = @parameterizable._querify_single @query_hash
84
+
85
+ it 'returns a query instance for the given hash', ->
86
+ expect(@result).to.be.an.instanceof slender_data.SingleQuery
87
+ expect(@result.to_hash()).to.eql @query_hash
88
+
89
+ it 'configures the created query with the default configuration values of the current query', ->
90
+ expect(@result.versioning).to.be.true
91
+ expect(@result.partial_entries).to.be.true
92
+
93
+ it 'configures the created query with teh query parameters of the current query', ->
94
+ expect(@result.full).to.be.true
95
+
96
+ context 'given a query object', ->
97
+
98
+ beforeEach ->
99
+ @query = new slender_data.SingleQuery @query_hash, @test_params
100
+ @result = @parameterizable._querify_single @query
101
+
102
+ it 'returns a given query directly', ->
103
+ expect(@result).to.equal @query
104
+
105
+
106
+ describe 'querify_multi', ->
107
+
108
+ beforeEach ->
109
+ @test_params.versioning = yes
110
+ @test_params.partial_entries = yes
111
+ @parameterizable = new slender_data.Parameterizable @test_params
112
+ @query_hash = ids: [3, 4], full: yes
113
+
114
+ context 'given a query hash', ->
115
+
116
+ beforeEach ->
117
+ @result = @parameterizable._querify_multi @query_hash
118
+
119
+ it 'returns a query instance for the given hash', ->
120
+ expect(@result).to.be.an.instanceof slender_data.MultiQuery
121
+ expect(@result.to_hash()).to.eql @query_hash
122
+
123
+ it 'configures the created query with the default configuration values of the current query', ->
124
+ expect(@result.versioning).to.be.true
125
+ expect(@result.partial_entries).to.be.true
126
+
127
+ it 'configures the created query with teh query parameters of the current query', ->
128
+ expect(@result.full).to.be.true
129
+
130
+ context 'given a query object', ->
131
+
132
+ beforeEach ->
133
+ @query = new slender_data.MultiQuery @query_hash, @test_params
134
+ @result = @parameterizable._querify_multi @query
135
+
136
+ it 'returns a given query directly', ->
137
+ expect(@result).to.equal @query
138
+
@@ -0,0 +1,659 @@
1
+ #= require spec_helper
2
+
3
+
4
+ describe 'PersistenceManager', ->
5
+
6
+ beforeEach ->
7
+ define_test_data this
8
+ @persistence_manager = new slender_data.PersistenceManager @test_params
9
+
10
+
11
+ describe 'add_to_cache', ->
12
+
13
+ beforeEach ->
14
+ @result = @persistence_manager.add_to_cache @user_1
15
+
16
+ it 'adds the described entry to the serverside cache', ->
17
+ expect(@persistence_manager.get user: @user_1).to.eql @user_1
18
+
19
+ it 'returns nothing', ->
20
+ expect(@result).to.be.undefined
21
+
22
+
23
+
24
+ describe 'add_many_to_cache', ->
25
+
26
+ beforeEach ->
27
+ @result = @persistence_manager.add_many_to_cache [ @user_1, @user_2 ]
28
+
29
+ it 'adds all described entries to the chache', ->
30
+ expect(@persistence_manager.get user: @user_1).to.eql @user_1
31
+ expect(@persistence_manager.get user: @user_2).to.eql @user_2
32
+
33
+ it 'returns nothing', ->
34
+ expect(@result).to.be.undefined
35
+
36
+
37
+
38
+ describe 'create', ->
39
+
40
+ beforeEach ->
41
+ @server_create_api = sinon.stub(@persistence_manager.server_api, 'create')
42
+ .yields user: @user_1
43
+ @result = @persistence_manager.create @user_1
44
+
45
+ it 'creates the entry on the server', ->
46
+ expect(@server_create_api).to.have.been.calledOnce
47
+ expect(@server_create_api).to.have.been.calledWith @user_1
48
+
49
+ it 'adds the server response to the cache', ->
50
+ expect(@persistence_manager.get user: @user_1).to.eql @user_1
51
+
52
+ it 'returns nothing', ->
53
+ expect(@result).to.be.undefined
54
+
55
+ it 'calls the given callback with an editable version of the created entry when done', (done) ->
56
+ @persistence_manager.create @user_1, (result) =>
57
+ expect(result).to.eql @user_1
58
+ expect(result).to.not.equal @user_1
59
+ done()
60
+
61
+
62
+ describe 'create_many', ->
63
+
64
+ beforeEach ->
65
+ @server_create_many_api = sinon.stub(@persistence_manager.server_api, 'create_many')
66
+ .yields users: [@user_1, @user_2]
67
+ @result = @persistence_manager.create_many [@user_1, @user_2]
68
+
69
+ it 'creates the entries on the server', ->
70
+ expect(@server_create_many_api).to.have.been.calledOnce
71
+ expect(@server_create_many_api).to.have.been.calledWith [@user_1, @user_2]
72
+
73
+ it 'adds the server response to the cache', ->
74
+ expect(@persistence_manager.get user: @user_1).to.eql @user_1
75
+ expect(@persistence_manager.get user: @user_2).to.eql @user_2
76
+
77
+ it 'returns nothing', ->
78
+ expect(@result).to.be.undefined
79
+
80
+ it 'calls the given callback when done', (done) ->
81
+ @persistence_manager.create_many [@user_1], done
82
+
83
+
84
+
85
+ describe 'delete', ->
86
+
87
+ beforeEach (done) ->
88
+ @persistence_manager.add_to_cache @user_1
89
+ @server_delete_api = sinon.stub(@persistence_manager.server_api, 'delete')
90
+ .yields username: 'one'
91
+ @persistence_manager.delete @user_1, (@result) =>
92
+ done()
93
+
94
+ it 'removes the given entry from the cache', ->
95
+ expect(@persistence_manager.get user: @user_1).to.be.undefined
96
+
97
+ it 'removes the given entry from the server', ->
98
+ expect(@server_delete_api).to.have.been.calledOnce
99
+ expect(@server_delete_api).to.have.been.calledWith @user_1
100
+
101
+ it 'calls the given callback with a description of the deleted entry', ->
102
+ expect(@result).to.eql username: 'one'
103
+
104
+
105
+ describe 'delete_many', ->
106
+
107
+ beforeEach (done) ->
108
+ @persistence_manager.add_many_to_cache [@user_1, @user_2]
109
+ @server_delete_many_api = sinon.stub(@persistence_manager.server_api, 'delete_many')
110
+ .yields usernames: ['one', 'two']
111
+ @persistence_manager.delete_many [@user_1, @user_2], (@result) => done()
112
+
113
+ it 'removes the given entries from the cache', ->
114
+ expect(@persistence_manager.get user: @user_1).to.be.undefined
115
+ expect(@persistence_manager.get user: @user_2).to.be.undefined
116
+
117
+ it 'removes the given entry from the server', ->
118
+ expect(@server_delete_many_api).to.have.been.calledOnce
119
+ expect(@server_delete_many_api).to.have.been.calledWith [@user_1, @user_2]
120
+
121
+ it 'calls the given callback with a description of the deleted entries', ->
122
+ expect(@result).to.eql usernames: ['one', 'two']
123
+
124
+
125
+
126
+ describe 'get', ->
127
+
128
+ describe 'normal functionality', ->
129
+
130
+ beforeEach ->
131
+ @persistence_manager.add_to_cache @user_1
132
+
133
+ it 'returns the described entry from the cache if it exists there', ->
134
+ expect(@persistence_manager.get user: @user_1).to.eql @user_1
135
+
136
+ it 'returns undefined if the described entry is not cached', ->
137
+ expect(@persistence_manager.get user: @user_2).to.be.undefined
138
+
139
+
140
+ describe 'partial/full functionality', ->
141
+
142
+ beforeEach ->
143
+ @test_params.partial_entries = yes
144
+ @persistence_manager = new slender_data.PersistenceManager @test_params
145
+
146
+ context 'partial entry in cache', ->
147
+
148
+ beforeEach ->
149
+ @persistence_manager.add_to_cache @partial_user_1
150
+
151
+ it 'returns the cached partial entry when partial entries are allowed', ->
152
+ result = @persistence_manager.get username: 'one', full: no
153
+ expect(result).to.eql @partial_user_1
154
+
155
+ it 'returns undefined when full entries are requested', ->
156
+ result = @persistence_manager.get username: 'one', full: yes
157
+ expect(result).to.be.undefined
158
+
159
+
160
+ context 'full entry in the cache', ->
161
+
162
+ beforeEach ->
163
+ @persistence_manager.add_to_cache @full_user_1
164
+
165
+ context 'partial entry requested', ->
166
+
167
+ beforeEach ->
168
+ @result = @persistence_manager.get username: 'one', full: no
169
+
170
+ it 'returns the cached full entry', ->
171
+ expect(@result).to.eql @full_user_1
172
+
173
+ context 'full entry requested', ->
174
+
175
+ beforeEach ->
176
+ @result = @persistence_manager.get username: 'one', full: yes
177
+
178
+ it 'returns the cached full entry', ->
179
+ expect(@result).to.eql @full_user_1
180
+
181
+
182
+
183
+ describe 'get_many', ->
184
+
185
+ describe 'normal functionality', ->
186
+
187
+ beforeEach ->
188
+ @persistence_manager.add_many_to_cache [@user_1, @user_3]
189
+ @result = @persistence_manager.get_many users: [@user_1, @user_2, @user_3]
190
+
191
+ it 'returns the cached entries', ->
192
+ expect(@result.found).to.eql [@user_1, @user_3]
193
+
194
+ it 'returns the ids of the missing entries', ->
195
+ expect(@result.missing).to.be.an.instanceof slender_data.MultiQuery
196
+ expect(@result.missing.ids()).to.eql ['two']
197
+
198
+
199
+ describe 'partial/full functionality', ->
200
+
201
+ beforeEach ->
202
+ @test_params.partial_entries = yes
203
+ @persistence_manager = new slender_data.PersistenceManager @test_params
204
+ @persistence_manager.add_many_to_cache [@partial_user_1, @full_user_2]
205
+
206
+ context 'partial entries requested', ->
207
+
208
+ beforeEach ->
209
+ @result = @persistence_manager.get_many
210
+ usernames: ['one', 'two', 'three'], full: no
211
+
212
+ it 'returns all matching cached entries as found', ->
213
+ expect(@result.found).to.eql [@partial_user_1, @full_user_2]
214
+
215
+ it 'returns the ids of missing entries as missing', ->
216
+ expect(@result.missing.to_hash()).to.eql usernames: ['three'], full: no
217
+
218
+ context 'full entries requested', ->
219
+
220
+ beforeEach ->
221
+ @result = @persistence_manager.get_many
222
+ usernames: ['one', 'two', 'three'], full: yes
223
+
224
+ it 'returns only full entries as found', ->
225
+ expect(@result.found).to.eql [@full_user_2]
226
+
227
+ it 'returns partial and missing entries as missing', ->
228
+ expect(@result.missing.to_hash()).to.eql usernames: ['one', 'three'], full: yes
229
+
230
+
231
+ describe 'versioning', ->
232
+
233
+ beforeEach ->
234
+ @test_params.versioning = yes
235
+ @persistence_manager = new slender_data.PersistenceManager @test_params
236
+ @persistence_manager.add_many_to_cache [@user_1_outdated, @user_2]
237
+ @result = @persistence_manager.get_many users: [@user_1, @user_2]
238
+
239
+ it 'returns only results of the right version', ->
240
+ expect(@result.found).to.eql [@user_2]
241
+ expect(@result.missing.to_hash()).to.eql users: [@user_1]
242
+
243
+
244
+ describe 'load', ->
245
+
246
+ beforeEach ->
247
+ @server_read_api = sinon.stub @persistence_manager.server_api, 'read'
248
+
249
+
250
+ describe 'normal behavior', ->
251
+
252
+ context 'described entry is in the cache', ->
253
+
254
+ beforeEach (done) ->
255
+ @persistence_manager.add_to_cache @user_1
256
+ @persistence_manager.load user: @user_1, (@result) =>
257
+ done()
258
+
259
+ it 'returns the entry directly from the cache', ->
260
+ expect(@result).to.eql @user_1
261
+
262
+ it 'does not query the server', ->
263
+ expect(@persistence_manager.server_api.read).to.not.have.been.called
264
+
265
+ context 'described entry is not in the cache', ->
266
+
267
+ beforeEach (done) ->
268
+ @server_read_api.yields(user: @user_1)
269
+ @persistence_manager.load user: @user_1, (@result) =>
270
+ done()
271
+
272
+ it 'loads the entry from the server', ->
273
+ server_read_api = @persistence_manager.server_api.read
274
+ expect(server_read_api).to.have.been.calledOnce
275
+ expect(server_read_api.args[0][0].to_hash()).to.eql user: @user_1
276
+
277
+ it 'adds the loaded entry to the cache', ->
278
+ expect(@persistence_manager.get user: @user_1).to.eql @user_1
279
+
280
+ it 'returns an editable copy of the entry loaded from the server', ->
281
+ expect(@result).to.eql @user_1
282
+ expect(@result).to.not.equal @user_1
283
+
284
+
285
+ describe 'partial entry functionality', ->
286
+
287
+ beforeEach ->
288
+ @test_params.partial_entries = yes
289
+ @persistence_manager = new slender_data.PersistenceManager @test_params
290
+ @server_read_api = sinon.stub(@persistence_manager.server_api, 'read')
291
+ .yields(user: @full_user_1)
292
+
293
+ context 'cache contains partial entry', ->
294
+
295
+ beforeEach ->
296
+ @persistence_manager.add_to_cache @partial_user_1
297
+
298
+ context 'full entry requested', (done) ->
299
+
300
+ beforeEach (done) ->
301
+ @persistence_manager.load {username: 'one', full: yes}, (@result) =>
302
+ done()
303
+
304
+ it 'loads the requested entry from the server', ->
305
+ expect(@server_read_api).to.have.been.calledOnce
306
+ expect(@server_read_api.args[0][0].to_hash()).to.have.property 'username',
307
+ 'one'
308
+
309
+ it 'replaces the cached partial entry with the loaded full entry', ->
310
+ expect(@persistence_manager.get username: 'one').to.eql @full_user_1
311
+
312
+ context 'partial entry requested', ->
313
+
314
+ beforeEach (done) ->
315
+ @persistence_manager.load {username: 'one', full: no}, (@result) =>
316
+ done()
317
+
318
+ it 'returns the entry from the cache', ->
319
+ expect(@result).to.eql @partial_user_1
320
+
321
+ it 'does not load data from the server', ->
322
+ expect(@server_read_api).to.not.have.been.called
323
+
324
+ context 'cache contains full entry', ->
325
+
326
+ beforeEach ->
327
+ @persistence_manager.add_to_cache @full_user_1
328
+
329
+ context 'full entry requested', ->
330
+
331
+ beforeEach (done) ->
332
+ @persistence_manager.load {username: 'one', full: yes}, (@result) =>
333
+ done()
334
+
335
+ it 'returns the entry from the cache', ->
336
+ expect(@result).to.eql @full_user_1
337
+
338
+ it 'does not load data from the server', ->
339
+ expect(@server_read_api).to.not.have.been.called
340
+
341
+ context 'partial entry requested', ->
342
+
343
+ beforeEach (done) ->
344
+ @persistence_manager.load {username: 'one', full: no}, (@result) =>
345
+ done()
346
+
347
+ it 'returns the full entry from the cache', ->
348
+ expect(@result).to.eql @full_user_1
349
+
350
+ it 'does not load data from the server', ->
351
+ expect(@server_read_api).to.not.have.been.called
352
+
353
+
354
+ describe 'versioning', ->
355
+
356
+ beforeEach ->
357
+ @test_params.versioning = yes
358
+ @persistence_manager = new slender_data.PersistenceManager @test_params
359
+ @server_read_api = sinon.stub(@persistence_manager.server_api, 'read')
360
+
361
+ context 'cache contains current entry', ->
362
+
363
+ beforeEach (done) ->
364
+ @persistence_manager.add_to_cache @user_1
365
+ @persistence_manager.load user: @user_1, (@result) => done()
366
+
367
+ it 'returns the cached entry', ->
368
+ expect(@result).to.eql @user_1
369
+
370
+ it 'does not load anything from the server', ->
371
+ expect(@server_read_api).to.not.have.been.called
372
+
373
+ context 'cache contains outdated entry', ->
374
+
375
+ beforeEach (done) ->
376
+ @persistence_manager.add_to_cache @user_1_outdated
377
+ @server_read_api.yields user: @user_1
378
+ @persistence_manager.load user: @user_1, (@result) => done()
379
+
380
+ it 'does not return the cached entry', ->
381
+ expect(@result).to.not.eql @user_1_outdated
382
+
383
+ it 'loads the current entry from the server', ->
384
+ expect(@server_read_api).to.have.been.calledOnce
385
+
386
+ it 'returns the current entry loaded from the server', ->
387
+ expect(@result).to.eql @user_1
388
+
389
+ it 'updates the cache with the newly loaded entry version', ->
390
+ expect(@persistence_manager.get user: @user_1).to.eql @user_1
391
+
392
+
393
+
394
+ describe 'load_many', ->
395
+
396
+ describe 'normal functionality', ->
397
+
398
+ beforeEach ->
399
+ @server_read_many_api = sinon.stub(@persistence_manager.server_api, 'read_many')
400
+
401
+ context 'all snippets are in the cache', ->
402
+
403
+ beforeEach ->
404
+ @persistence_manager.add_many_to_cache [@user_1, @user_2]
405
+
406
+ it 'returns all requested snippets', (done) ->
407
+ @persistence_manager.load_many users: [@user_1, @user_2], (users) =>
408
+ expect(users).to.eql [@user_1, @user_2]
409
+ done()
410
+
411
+ it 'does not query the server', (done) ->
412
+ @persistence_manager.load_many users: [@user_1, @user_2], =>
413
+ expect(@server_read_many_api).to.not.have.been.called
414
+ done()
415
+
416
+
417
+ context 'some snippets are not cached', ->
418
+
419
+ beforeEach ->
420
+ @persistence_manager.add_many_to_cache [@user_1, @user_3]
421
+ @user_2_from_server = slender_data.clone_hash @user_2
422
+ @server_read_many_api.yields users: [@user_2_from_server]
423
+
424
+ it 'returns all requested snippets', (done) ->
425
+ @persistence_manager.load_many users: [@user_1, @user_2, @user_3], (users) =>
426
+ expect(users).to.have.length 3
427
+ user_ids = (user.username for user in users)
428
+ expect(user_ids).to.include 'one'
429
+ expect(user_ids).to.include 'two'
430
+ expect(user_ids).to.include 'three'
431
+ done()
432
+
433
+ it 'loads the missing snippets from the server', (done) ->
434
+ @persistence_manager.load_many users: [@user_1, @user_2, @user_3], (users) =>
435
+ server_args = @server_read_many_api.args[0][0].to_hash()
436
+ expect(server_args).to.eql users: [@user_2]
437
+ done()
438
+
439
+ it 'adds the loaded entries to the cache', ->
440
+ @persistence_manager.load_many users: [@user_2], (users) =>
441
+ expect(users[0]).to.eql @user_2
442
+ expect(users[0]).to.not.equal @user_2_from_server
443
+
444
+
445
+
446
+ describe 'partial entry functionality', ->
447
+
448
+ beforeEach ->
449
+ @test_params.partial_entries = yes
450
+ @persistence_manager = new slender_data.PersistenceManager @test_params
451
+ @persistence_manager.add_many_to_cache [@partial_user_1, @full_user_2]
452
+ @server_read_many_api = sinon.stub(@persistence_manager.server_api, 'read_many')
453
+ .yields(users: [ @full_user_1, @full_user_3 ])
454
+
455
+ context 'full entries requested', (done) ->
456
+
457
+ beforeEach (done) ->
458
+ @persistence_manager.load_many {usernames: ['one', 'two', 'three'], full: yes},
459
+ (@result) => done()
460
+
461
+ it 'loads the partial entries from the server', ->
462
+ expect(@server_read_many_api).to.have.been.calledOnce
463
+ server_args = @server_read_many_api.args[0][0]
464
+ expect(server_args.to_hash().usernames).to.eql ['one', 'three']
465
+
466
+ it 'replaces the cached partial entries with the loaded full entries', ->
467
+ expect(@persistence_manager.get username: 'one').to.eql @full_user_1
468
+ expect(@persistence_manager.get username: 'two').to.eql @full_user_2
469
+
470
+ it 'returns the full entries', ->
471
+ expect(@result).to.have.length 3
472
+ emails = (entry.email for entry in @result)
473
+ expect(emails).to.include 'one@example.com'
474
+ expect(emails).to.include 'two@example.com'
475
+ expect(emails).to.include 'three@example.com'
476
+
477
+
478
+ context 'partial entries requested', ->
479
+
480
+ beforeEach (done) ->
481
+ @persistence_manager.load_many {usernames: ['one', 'two'], full: no},
482
+ (@result) => done()
483
+
484
+ it 'returns the entries from the cache', ->
485
+ expect(@result).to.eql [@partial_user_1, @full_user_2]
486
+
487
+ it 'does not load data from the server', ->
488
+ expect(@server_read_many_api).to.not.have.been.called
489
+
490
+
491
+ describe 'versioning', ->
492
+
493
+ beforeEach (done) ->
494
+ @test_params.versioning = yes
495
+ @persistence_manager = new slender_data.PersistenceManager @test_params
496
+ @persistence_manager.add_many_to_cache [@user_1_outdated, @user_2]
497
+ @server_read_many_api = sinon.stub(@persistence_manager.server_api,
498
+ 'read_many')
499
+ .yields(users: [@user_1])
500
+ @persistence_manager.load_many users: [@user_1, @user_2],
501
+ (@result) => done()
502
+
503
+ it 'returns all requested entries', ->
504
+ expect(@result).to.eql [@user_2, @user_1]
505
+
506
+ it 'loads only outdated entries from the server', ->
507
+ expect(@server_read_many_api).to.have.been.calledOnce
508
+ expect(@server_read_many_api.args[0][0].to_hash()).to.eql users: [@user_1]
509
+
510
+ it 'adds the loaded entries to the cache', ->
511
+ expect(@persistence_manager.get username: 'one').to.eql @user_1
512
+
513
+
514
+ describe 'merge', ->
515
+
516
+ beforeEach ->
517
+ @merged_user_data = email: 'merged@example.com'
518
+ @merged_user_server_response = username: 'merged server', timestamp: 1
519
+ @persistence_manager.add_many_to_cache [@user_1, @user_2, @user_3]
520
+ @callback = sinon.stub()
521
+ @server_merge_api = sinon.stub(@persistence_manager.server_api, 'merge')
522
+ .yields(user: @merged_user_server_response)
523
+ @persistence_manager.merge [@user_1.username, @user_2.username],
524
+ @merged_user_data,
525
+ @callback
526
+
527
+ it 'performes the merge on the server', ->
528
+ expect(@server_merge_api).to.have.been.calledOnce
529
+
530
+ it 'removes the old users from the client cache', ->
531
+ expect(@persistence_manager.get user: @user_1).to.be.undefined
532
+ expect(@persistence_manager.get user: @user_2).to.be.undefined
533
+ expect(@persistence_manager.get user: @user_3).to.eql @user_3
534
+
535
+ it 'adds the user provided by the server to the client cache', ->
536
+ cached_user = @persistence_manager.get user: @merged_user_server_response
537
+ expect(cached_user).to.eql @merged_user_server_response
538
+
539
+ it 'calls the given callback when done', ->
540
+ expect(@callback).to.have.been.calledOnce
541
+
542
+ it 'returns the editable user in the callback', ->
543
+ callback_args = @callback.args[0][0]
544
+ expect(callback_args).to.eql @merged_user_server_response
545
+ expect(callback_args).to.not.equal @merged_user_server_response
546
+
547
+
548
+
549
+ describe 'update', ->
550
+
551
+ beforeEach ->
552
+ @persistence_manager.add_to_cache @user_1
553
+ @user = @persistence_manager.get user: @user_1
554
+ @server_update_api = sinon.stub(@persistence_manager.server_api, 'update')
555
+ .yields user: @user
556
+
557
+
558
+ context 'nothing is changed', ->
559
+
560
+ beforeEach (done) ->
561
+ @persistence_manager.update @user, (@result) => done()
562
+
563
+ it 'does not make a call to the server', ->
564
+ expect(@server_update_api).to.not.have.been.called
565
+
566
+ it 'calls the callback with the given entry', ->
567
+ expect(@result).to.eql user: @user_1
568
+
569
+ it 'works without a callback provided', ->
570
+ @persistence_manager.update @user
571
+
572
+
573
+ context 'entry is changed', ->
574
+
575
+ beforeEach (done) ->
576
+ @user.email = 'new_one@example.com'
577
+ @persistence_manager.update @user, (@result) => done()
578
+
579
+ it 'calls the server with only the changed attributes as payload', ->
580
+ expect(@server_update_api).to.have.been.calledOnce
581
+ expect(@server_update_api).to.have.been.calledWith
582
+ username: 'one', email: 'new_one@example.com'
583
+
584
+ it 'calls the callback with the server response when done', ->
585
+ expect(@result).to.eql user: @user
586
+
587
+ it 'stores the now persisted changes on the client', (done) ->
588
+ @persistence_manager.update @user, =>
589
+ @persistence_manager.update @user, =>
590
+ expect(@persistence_manager.server_api.update).to.have.been.calledOnce
591
+ done()
592
+
593
+ it 'works without a given callback', ->
594
+ @persistence_manager.update @user
595
+
596
+
597
+
598
+ describe 'update_many', ->
599
+
600
+ beforeEach ->
601
+ @persistence_manager.add_many_to_cache [@user_1, @user_2, @user_3]
602
+ @user_1_changed = @persistence_manager.get user: @user_1
603
+ @user_2_changed = @persistence_manager.get user: @user_2
604
+ @user_3_changed = @persistence_manager.get user: @user_3
605
+ @server_update_many_api = sinon.stub @persistence_manager.server_api,
606
+ 'update_many'
607
+
608
+ context 'nothing is changed', ->
609
+
610
+ beforeEach (done) ->
611
+ @server_update_many_api.yields users: [ @user_1_changed,
612
+ @user_2_changed ]
613
+ @persistence_manager.update_many [@user_1_changed, @user_2_changed],
614
+ (@result) => done()
615
+
616
+ it 'does not call the server', ->
617
+ expect(@server_update_many_api).to.not.have.been.called
618
+
619
+ it 'calls the callback with the server response', ->
620
+ expect(@result).to.eql users: [@user_1_changed, @user_2_changed]
621
+
622
+ it 'works without a given callback', ->
623
+ @persistence_manager.update_many [@user_1_changed]
624
+
625
+
626
+ context 'some entries are changed', ->
627
+
628
+ beforeEach (done) ->
629
+ @user_1_changed.email = 'new_one@example.com'
630
+ @user_3_changed.timestamp = 3
631
+ @server_update_many_api.yields users: [ @user_1_changed,
632
+ @user_3_changed ]
633
+ @persistence_manager.update_many [ @user_1_changed
634
+ @user_2_changed
635
+ @user_3_changed ],
636
+ (@result) => done()
637
+
638
+ it 'calls the server with only the changed attributes as payload', ->
639
+ expect(@server_update_many_api).to.have.been.calledOnce
640
+ update_args = @server_update_many_api.args[0][0]
641
+ expect(update_args[0]).to.eql username: 'one', email: 'new_one@example.com'
642
+ expect(update_args[1]).to.eql username: 'three', timestamp: 3
643
+
644
+ it 'calls the callback with the server response', ->
645
+ expect(@result).to.eql users: [@user_1_changed, @user_3_changed]
646
+
647
+ it 'stores the now persisted changes on the client', (done) ->
648
+ @persistence_manager.update_many [ @user_1_changed
649
+ @user_2_changed
650
+ @user_3_changed ], =>
651
+ @persistence_manager.update_many [ @user_1_changed
652
+ @user_2_changed
653
+ @user_3_changed ], =>
654
+ expect(@server_update_many_api).to.have.been.calledOnce
655
+ done()
656
+
657
+ it 'works without a given callback', ->
658
+ @persistence_manager.update_many [@user_1]
659
+