slender_data 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+