hyper-mesh 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (469) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +27 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +11 -0
  5. data/.travis.yml +4 -0
  6. data/CODE_OF_CONDUCT.md +13 -0
  7. data/Gemfile +5 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +396 -0
  10. data/Rakefile +6 -0
  11. data/app/controllers/reactive_record/application_controller.rb +4 -0
  12. data/app/controllers/reactive_record/reactive_record_controller.rb +49 -0
  13. data/bin/console +14 -0
  14. data/bin/setup +7 -0
  15. data/codeship.database.yml +18 -0
  16. data/config/routes.rb +7 -0
  17. data/docs/action_cable_quickstart.md +151 -0
  18. data/docs/authorization-policies.md +449 -0
  19. data/docs/client_side_scoping.md +103 -0
  20. data/docs/pusher_quickstart.md +0 -0
  21. data/docs/simple_poller_quickstart.md +121 -0
  22. data/docs/todo-example.md +116 -0
  23. data/docs/words-example.md +65 -0
  24. data/examples/action-cable/.gitignore +21 -0
  25. data/examples/action-cable/Gemfile +58 -0
  26. data/examples/action-cable/Gemfile.lock +247 -0
  27. data/examples/action-cable/README.md +24 -0
  28. data/examples/action-cable/Rakefile +6 -0
  29. data/examples/action-cable/app/assets/config/manifest.js +3 -0
  30. data/examples/action-cable/app/assets/javascripts/application.js +18 -0
  31. data/examples/action-cable/app/assets/stylesheets/application.css +15 -0
  32. data/examples/action-cable/app/controllers/application_controller.rb +3 -0
  33. data/examples/action-cable/app/controllers/test_controller.rb +6 -0
  34. data/examples/action-cable/app/models/models.rb +2 -0
  35. data/examples/action-cable/app/models/public/application_record.rb +3 -0
  36. data/examples/action-cable/app/models/public/word.rb +2 -0
  37. data/examples/action-cable/app/policies/application_policy.rb +6 -0
  38. data/examples/action-cable/app/views/components.rb +17 -0
  39. data/examples/action-cable/app/views/components/app.rb +18 -0
  40. data/examples/action-cable/app/views/layouts/application.html.erb +14 -0
  41. data/examples/action-cable/app/views/layouts/mailer.html.erb +13 -0
  42. data/examples/action-cable/app/views/layouts/mailer.text.erb +1 -0
  43. data/examples/action-cable/bin/bundle +3 -0
  44. data/examples/action-cable/bin/rails +9 -0
  45. data/examples/action-cable/bin/rake +9 -0
  46. data/examples/action-cable/bin/setup +34 -0
  47. data/examples/action-cable/bin/spring +15 -0
  48. data/examples/action-cable/bin/update +29 -0
  49. data/examples/action-cable/config.ru +5 -0
  50. data/examples/action-cable/config/application.rb +30 -0
  51. data/examples/action-cable/config/boot.rb +3 -0
  52. data/examples/action-cable/config/cable.yml +9 -0
  53. data/examples/action-cable/config/database.yml +25 -0
  54. data/examples/action-cable/config/environment.rb +5 -0
  55. data/examples/action-cable/config/environments/development.rb +45 -0
  56. data/examples/action-cable/config/environments/production.rb +86 -0
  57. data/examples/action-cable/config/environments/test.rb +42 -0
  58. data/examples/action-cable/config/initializers/application_controller_renderer.rb +6 -0
  59. data/examples/action-cable/config/initializers/assets.rb +11 -0
  60. data/examples/action-cable/config/initializers/backtrace_silencers.rb +7 -0
  61. data/examples/action-cable/config/initializers/cookies_serializer.rb +5 -0
  62. data/examples/action-cable/config/initializers/filter_parameter_logging.rb +4 -0
  63. data/examples/action-cable/config/initializers/inflections.rb +16 -0
  64. data/examples/action-cable/config/initializers/mime_types.rb +4 -0
  65. data/examples/action-cable/config/initializers/new_framework_defaults.rb +24 -0
  66. data/examples/action-cable/config/initializers/session_store.rb +3 -0
  67. data/examples/action-cable/config/initializers/synchromesh.rb +5 -0
  68. data/examples/action-cable/config/initializers/wrap_parameters.rb +14 -0
  69. data/examples/action-cable/config/locales/en.yml +23 -0
  70. data/examples/action-cable/config/puma.rb +47 -0
  71. data/examples/action-cable/config/routes.rb +5 -0
  72. data/examples/action-cable/config/secrets.yml +22 -0
  73. data/examples/action-cable/config/spring.rb +6 -0
  74. data/examples/action-cable/db/migrate/20160921223808_create_words.rb +9 -0
  75. data/examples/action-cable/db/schema.rb +21 -0
  76. data/examples/action-cable/log/.keep +0 -0
  77. data/examples/action-cable/public/404.html +67 -0
  78. data/examples/action-cable/public/422.html +67 -0
  79. data/examples/action-cable/public/500.html +66 -0
  80. data/examples/action-cable/public/apple-touch-icon-precomposed.png +0 -0
  81. data/examples/action-cable/public/apple-touch-icon.png +0 -0
  82. data/examples/action-cable/public/favicon.ico +0 -0
  83. data/examples/action-cable/public/robots.txt +5 -0
  84. data/examples/action-cable/rails_cache_dir2/C91/480/synchromesh_active_connections +0 -0
  85. data/examples/action-cable/tmp/.keep +0 -0
  86. data/examples/action-cable/vendor/assets/javascripts/.keep +0 -0
  87. data/examples/action-cable/vendor/assets/stylesheets/.keep +0 -0
  88. data/examples/simple-poller/.gitignore +21 -0
  89. data/examples/simple-poller/Gemfile +64 -0
  90. data/examples/simple-poller/Gemfile.lock +272 -0
  91. data/examples/simple-poller/README.md +24 -0
  92. data/examples/simple-poller/Rakefile +6 -0
  93. data/examples/simple-poller/app/assets/config/manifest.js +3 -0
  94. data/examples/simple-poller/app/assets/images/.keep +0 -0
  95. data/examples/simple-poller/app/assets/javascripts/application.js +20 -0
  96. data/examples/simple-poller/app/assets/javascripts/channels/.keep +0 -0
  97. data/examples/simple-poller/app/assets/stylesheets/application.css +15 -0
  98. data/examples/simple-poller/app/channels/application_cable/channel.rb +4 -0
  99. data/examples/simple-poller/app/channels/application_cable/connection.rb +4 -0
  100. data/examples/simple-poller/app/controllers/application_controller.rb +3 -0
  101. data/examples/simple-poller/app/controllers/concerns/.keep +0 -0
  102. data/examples/simple-poller/app/controllers/test_controller.rb +6 -0
  103. data/examples/simple-poller/app/helpers/application_helper.rb +2 -0
  104. data/examples/simple-poller/app/jobs/application_job.rb +2 -0
  105. data/examples/simple-poller/app/mailers/application_mailer.rb +4 -0
  106. data/examples/simple-poller/app/models/concerns/.keep +0 -0
  107. data/examples/simple-poller/app/models/models.rb +2 -0
  108. data/examples/simple-poller/app/models/public/.keep +0 -0
  109. data/examples/simple-poller/app/models/public/application_record.rb +3 -0
  110. data/examples/simple-poller/app/models/public/word.rb +2 -0
  111. data/examples/simple-poller/app/policies/application_policy.rb +5 -0
  112. data/examples/simple-poller/app/views/components.rb +18 -0
  113. data/examples/simple-poller/app/views/components/.keep +0 -0
  114. data/examples/simple-poller/app/views/components/app.rb +40 -0
  115. data/examples/simple-poller/app/views/layouts/application.html.erb +14 -0
  116. data/examples/simple-poller/app/views/layouts/mailer.html.erb +13 -0
  117. data/examples/simple-poller/app/views/layouts/mailer.text.erb +1 -0
  118. data/examples/simple-poller/bin/bundle +3 -0
  119. data/examples/simple-poller/bin/rails +9 -0
  120. data/examples/simple-poller/bin/rake +9 -0
  121. data/examples/simple-poller/bin/setup +34 -0
  122. data/examples/simple-poller/bin/spring +16 -0
  123. data/examples/simple-poller/bin/update +29 -0
  124. data/examples/simple-poller/config.ru +5 -0
  125. data/examples/simple-poller/config/application.rb +20 -0
  126. data/examples/simple-poller/config/boot.rb +3 -0
  127. data/examples/simple-poller/config/cable.yml +9 -0
  128. data/examples/simple-poller/config/database.yml +25 -0
  129. data/examples/simple-poller/config/environment.rb +5 -0
  130. data/examples/simple-poller/config/environments/development.rb +44 -0
  131. data/examples/simple-poller/config/environments/production.rb +86 -0
  132. data/examples/simple-poller/config/environments/test.rb +42 -0
  133. data/examples/simple-poller/config/initializers/application_controller_renderer.rb +6 -0
  134. data/examples/simple-poller/config/initializers/assets.rb +11 -0
  135. data/examples/simple-poller/config/initializers/backtrace_silencers.rb +7 -0
  136. data/examples/simple-poller/config/initializers/cookies_serializer.rb +5 -0
  137. data/examples/simple-poller/config/initializers/filter_parameter_logging.rb +4 -0
  138. data/examples/simple-poller/config/initializers/inflections.rb +16 -0
  139. data/examples/simple-poller/config/initializers/mime_types.rb +4 -0
  140. data/examples/simple-poller/config/initializers/new_framework_defaults.rb +24 -0
  141. data/examples/simple-poller/config/initializers/session_store.rb +3 -0
  142. data/examples/simple-poller/config/initializers/synchromesh.rb +15 -0
  143. data/examples/simple-poller/config/initializers/wrap_parameters.rb +14 -0
  144. data/examples/simple-poller/config/locales/en.yml +23 -0
  145. data/examples/simple-poller/config/puma.rb +47 -0
  146. data/examples/simple-poller/config/routes.rb +5 -0
  147. data/examples/simple-poller/config/secrets.yml +22 -0
  148. data/examples/simple-poller/config/spring.rb +6 -0
  149. data/examples/simple-poller/db/migrate/20161013220135_create_words.rb +9 -0
  150. data/examples/simple-poller/db/schema.rb +21 -0
  151. data/examples/simple-poller/db/seeds.rb +7 -0
  152. data/examples/simple-poller/lib/assets/.keep +0 -0
  153. data/examples/simple-poller/lib/tasks/.keep +0 -0
  154. data/examples/simple-poller/log/.keep +0 -0
  155. data/examples/simple-poller/public/404.html +67 -0
  156. data/examples/simple-poller/public/422.html +67 -0
  157. data/examples/simple-poller/public/500.html +66 -0
  158. data/examples/simple-poller/public/apple-touch-icon-precomposed.png +0 -0
  159. data/examples/simple-poller/public/apple-touch-icon.png +0 -0
  160. data/examples/simple-poller/public/favicon.ico +0 -0
  161. data/examples/simple-poller/public/robots.txt +5 -0
  162. data/examples/simple-poller/test/controllers/.keep +0 -0
  163. data/examples/simple-poller/test/fixtures/.keep +0 -0
  164. data/examples/simple-poller/test/fixtures/files/.keep +0 -0
  165. data/examples/simple-poller/test/fixtures/words.yml +7 -0
  166. data/examples/simple-poller/test/helpers/.keep +0 -0
  167. data/examples/simple-poller/test/integration/.keep +0 -0
  168. data/examples/simple-poller/test/mailers/.keep +0 -0
  169. data/examples/simple-poller/test/models/.keep +0 -0
  170. data/examples/simple-poller/test/models/word_test.rb +7 -0
  171. data/examples/simple-poller/test/test_helper.rb +10 -0
  172. data/examples/simple-poller/tmp/.keep +0 -0
  173. data/examples/simple-poller/vendor/assets/javascripts/.keep +0 -0
  174. data/examples/simple-poller/vendor/assets/stylesheets/.keep +0 -0
  175. data/examples/words/.gitignore +21 -0
  176. data/examples/words/Gemfile +58 -0
  177. data/examples/words/Gemfile.lock +247 -0
  178. data/examples/words/README.md +24 -0
  179. data/examples/words/Rakefile +6 -0
  180. data/examples/words/app/assets/config/manifest.js +3 -0
  181. data/examples/words/app/assets/javascripts/application.js +18 -0
  182. data/examples/words/app/assets/stylesheets/application.css +15 -0
  183. data/examples/words/app/controllers/application_controller.rb +3 -0
  184. data/examples/words/app/controllers/test_controller.rb +6 -0
  185. data/examples/words/app/models/models.rb +2 -0
  186. data/examples/words/app/models/public/application_record.rb +3 -0
  187. data/examples/words/app/models/public/word.rb +10 -0
  188. data/examples/words/app/policies/application_policy.rb +6 -0
  189. data/examples/words/app/views/components.rb +16 -0
  190. data/examples/words/app/views/components/app.rb +31 -0
  191. data/examples/words/app/views/layouts/application.html.erb +14 -0
  192. data/examples/words/app/views/layouts/mailer.html.erb +13 -0
  193. data/examples/words/app/views/layouts/mailer.text.erb +1 -0
  194. data/examples/words/bin/bundle +3 -0
  195. data/examples/words/bin/rails +9 -0
  196. data/examples/words/bin/rake +9 -0
  197. data/examples/words/bin/setup +34 -0
  198. data/examples/words/bin/spring +15 -0
  199. data/examples/words/bin/update +29 -0
  200. data/examples/words/config.ru +5 -0
  201. data/examples/words/config/application.rb +30 -0
  202. data/examples/words/config/boot.rb +3 -0
  203. data/examples/words/config/cable.yml +9 -0
  204. data/examples/words/config/database.yml +25 -0
  205. data/examples/words/config/environment.rb +5 -0
  206. data/examples/words/config/environments/development.rb +45 -0
  207. data/examples/words/config/environments/production.rb +86 -0
  208. data/examples/words/config/environments/test.rb +42 -0
  209. data/examples/words/config/initializers/application_controller_renderer.rb +6 -0
  210. data/examples/words/config/initializers/assets.rb +11 -0
  211. data/examples/words/config/initializers/backtrace_silencers.rb +7 -0
  212. data/examples/words/config/initializers/cookies_serializer.rb +5 -0
  213. data/examples/words/config/initializers/filter_parameter_logging.rb +4 -0
  214. data/examples/words/config/initializers/inflections.rb +16 -0
  215. data/examples/words/config/initializers/mime_types.rb +4 -0
  216. data/examples/words/config/initializers/new_framework_defaults.rb +24 -0
  217. data/examples/words/config/initializers/session_store.rb +3 -0
  218. data/examples/words/config/initializers/synchromesh.rb +5 -0
  219. data/examples/words/config/initializers/wrap_parameters.rb +14 -0
  220. data/examples/words/config/locales/en.yml +23 -0
  221. data/examples/words/config/puma.rb +47 -0
  222. data/examples/words/config/routes.rb +5 -0
  223. data/examples/words/config/secrets.yml +22 -0
  224. data/examples/words/config/spring.rb +6 -0
  225. data/examples/words/db/migrate/20160921223808_create_words.rb +9 -0
  226. data/examples/words/db/schema.rb +28 -0
  227. data/examples/words/log/.keep +0 -0
  228. data/examples/words/public/404.html +67 -0
  229. data/examples/words/public/422.html +67 -0
  230. data/examples/words/public/500.html +66 -0
  231. data/examples/words/public/apple-touch-icon-precomposed.png +0 -0
  232. data/examples/words/public/apple-touch-icon.png +0 -0
  233. data/examples/words/public/favicon.ico +0 -0
  234. data/examples/words/public/robots.txt +5 -0
  235. data/examples/words/tmp/.keep +0 -0
  236. data/examples/words/vendor/assets/javascripts/.keep +0 -0
  237. data/examples/words/vendor/assets/stylesheets/.keep +0 -0
  238. data/hyper-mesh.gemspec +82 -0
  239. data/lib/active_record_base.rb +152 -0
  240. data/lib/enumerable/pluck.rb +6 -0
  241. data/lib/hyper-mesh.rb +62 -0
  242. data/lib/hypermesh/version.rb +3 -0
  243. data/lib/opal/equality_patches.rb +15 -0
  244. data/lib/opal/parse_patch.rb +14 -0
  245. data/lib/opal/set_patches.rb +8 -0
  246. data/lib/reactive_record/active_record/aggregations.rb +69 -0
  247. data/lib/reactive_record/active_record/associations.rb +111 -0
  248. data/lib/reactive_record/active_record/base.rb +9 -0
  249. data/lib/reactive_record/active_record/class_methods.rb +177 -0
  250. data/lib/reactive_record/active_record/error.rb +26 -0
  251. data/lib/reactive_record/active_record/instance_methods.rb +129 -0
  252. data/lib/reactive_record/active_record/public_columns_hash.rb +19 -0
  253. data/lib/reactive_record/active_record/reactive_record/base.rb +520 -0
  254. data/lib/reactive_record/active_record/reactive_record/collection.rb +517 -0
  255. data/lib/reactive_record/active_record/reactive_record/column_types.rb +67 -0
  256. data/lib/reactive_record/active_record/reactive_record/dummy_value.rb +218 -0
  257. data/lib/reactive_record/active_record/reactive_record/isomorphic_base.rb +532 -0
  258. data/lib/reactive_record/active_record/reactive_record/reactive_set_relationship_helpers.rb +189 -0
  259. data/lib/reactive_record/active_record/reactive_record/scoped_collection.rb +62 -0
  260. data/lib/reactive_record/active_record/reactive_record/unscoped_collection.rb +16 -0
  261. data/lib/reactive_record/active_record/reactive_record/while_loading.rb +299 -0
  262. data/lib/reactive_record/engine.rb +13 -0
  263. data/lib/reactive_record/interval.rb +190 -0
  264. data/lib/reactive_record/permissions.rb +102 -0
  265. data/lib/reactive_record/pry.rb +13 -0
  266. data/lib/reactive_record/reactive_scope.rb +18 -0
  267. data/lib/reactive_record/scope_description.rb +108 -0
  268. data/lib/reactive_record/serializers.rb +7 -0
  269. data/lib/reactive_record/server_data_cache.rb +347 -0
  270. data/lib/reactive_record/version.rb +3 -0
  271. data/lib/sources/hyper-mesh/pusher.js +98 -0
  272. data/lib/synchromesh/action_cable.rb +39 -0
  273. data/lib/synchromesh/client_drivers.rb +357 -0
  274. data/lib/synchromesh/configuration.rb +40 -0
  275. data/lib/synchromesh/connection.rb +144 -0
  276. data/lib/synchromesh/policy.rb +504 -0
  277. data/lib/synchromesh/reactive_record/permission_patches.rb +43 -0
  278. data/lib/synchromesh/synchromesh.rb +155 -0
  279. data/lib/synchromesh/synchromesh_controller.rb +154 -0
  280. data/logo.jpg +0 -0
  281. data/path_release_steps.md +0 -0
  282. data/reactive_record_test_app/Gemfile +15 -0
  283. data/reactive_record_test_app/Gemfile.lock +209 -0
  284. data/reactive_record_test_app/README.rdoc +261 -0
  285. data/reactive_record_test_app/Rakefile +7 -0
  286. data/reactive_record_test_app/app/assets/javascripts/application.rb +5 -0
  287. data/reactive_record_test_app/app/assets/javascripts/components/another_component.rb +24 -0
  288. data/reactive_record_test_app/app/assets/javascripts/components/empty_component.rb +6 -0
  289. data/reactive_record_test_app/app/assets/javascripts/components/todo_item_component.js.rb +16 -0
  290. data/reactive_record_test_app/app/assets/javascripts/components/todos_component.js.rb +42 -0
  291. data/reactive_record_test_app/app/assets/javascripts/components/todos_main_component.rb +49 -0
  292. data/reactive_record_test_app/app/assets/javascripts/react_js_test_only.js +21618 -0
  293. data/reactive_record_test_app/app/assets/javascripts/reactive_record_config.js +2 -0
  294. data/reactive_record_test_app/app/assets/javascripts/spec/reactive_record_xspec.js.rb +42 -0
  295. data/reactive_record_test_app/app/assets/stylesheets/application.css +13 -0
  296. data/reactive_record_test_app/app/controllers/application_controller.rb +8 -0
  297. data/reactive_record_test_app/app/controllers/home_controller.rb +7 -0
  298. data/reactive_record_test_app/app/controllers/test_controller.rb +7 -0
  299. data/reactive_record_test_app/app/helpers/application_helper.rb +2 -0
  300. data/reactive_record_test_app/app/mailers/.gitkeep +0 -0
  301. data/reactive_record_test_app/app/models/.gitkeep +0 -0
  302. data/reactive_record_test_app/app/policies/application_policy.rb +5 -0
  303. data/reactive_record_test_app/app/views/components.rb +4 -0
  304. data/reactive_record_test_app/app/views/components/test.rb +18 -0
  305. data/reactive_record_test_app/app/views/home/index.html.erb +1 -0
  306. data/reactive_record_test_app/app/views/layouts/application.html.erb +17 -0
  307. data/reactive_record_test_app/app/views/models.rb +1 -0
  308. data/reactive_record_test_app/app/views/models/address.rb +13 -0
  309. data/reactive_record_test_app/app/views/models/comment.rb +19 -0
  310. data/reactive_record_test_app/app/views/models/todo_item.rb +36 -0
  311. data/reactive_record_test_app/app/views/models/user.rb +78 -0
  312. data/reactive_record_test_app/config.ru +33 -0
  313. data/reactive_record_test_app/config/application.rb +73 -0
  314. data/reactive_record_test_app/config/boot.rb +10 -0
  315. data/reactive_record_test_app/config/database.yml +25 -0
  316. data/reactive_record_test_app/config/environment.rb +5 -0
  317. data/reactive_record_test_app/config/environments/development.rb +43 -0
  318. data/reactive_record_test_app/config/environments/production.rb +70 -0
  319. data/reactive_record_test_app/config/environments/test.rb +41 -0
  320. data/reactive_record_test_app/config/initializers/backtrace_silencers.rb +7 -0
  321. data/reactive_record_test_app/config/initializers/inflections.rb +15 -0
  322. data/reactive_record_test_app/config/initializers/mime_types.rb +5 -0
  323. data/reactive_record_test_app/config/initializers/secret_token.rb +7 -0
  324. data/reactive_record_test_app/config/initializers/session_store.rb +8 -0
  325. data/reactive_record_test_app/config/initializers/wrap_parameters.rb +14 -0
  326. data/reactive_record_test_app/config/locales/en.yml +5 -0
  327. data/reactive_record_test_app/config/routes.rb +7 -0
  328. data/reactive_record_test_app/db/migrate/20150617002932_create_todo_items.rb +11 -0
  329. data/reactive_record_test_app/db/migrate/20150617134028_create_users.rb +14 -0
  330. data/reactive_record_test_app/db/migrate/20150729195556_add_address_to_user.rb +20 -0
  331. data/reactive_record_test_app/db/migrate/20150826142045_create_comments.rb +10 -0
  332. data/reactive_record_test_app/db/migrate/20150828172008_add_single_comment_to_todo_item.rb +5 -0
  333. data/reactive_record_test_app/db/migrate/20150908184118_add_address_id_to_user.rb +5 -0
  334. data/reactive_record_test_app/db/migrate/20150917220236_add_second_address_to_user.rb +10 -0
  335. data/reactive_record_test_app/db/migrate/20151009000111_add_test_data_attributes_to_user.rb +6 -0
  336. data/reactive_record_test_app/db/migrate/20160129182544_add_test_enum_to_user.rb +5 -0
  337. data/reactive_record_test_app/db/schema.rb +63 -0
  338. data/reactive_record_test_app/db/seeds.rb +60 -0
  339. data/reactive_record_test_app/public/404.html +26 -0
  340. data/reactive_record_test_app/public/422.html +26 -0
  341. data/reactive_record_test_app/public/500.html +25 -0
  342. data/reactive_record_test_app/public/favicon.ico +0 -0
  343. data/reactive_record_test_app/script/rails +6 -0
  344. data/reactive_record_test_app/spec-opal/active-record/aggregations_spec.rb +41 -0
  345. data/reactive_record_test_app/spec-opal/active-record/associations_spec.rb +75 -0
  346. data/reactive_record_test_app/spec-opal/active-record/base_spec.rb +126 -0
  347. data/reactive_record_test_app/spec-opal/active-record/dummy_value_spec.rb +27 -0
  348. data/reactive_record_test_app/spec-opal/active-record/edge_cases_spec.rb +116 -0
  349. data/reactive_record_test_app/spec-opal/active-record/enum_spec.rb +43 -0
  350. data/reactive_record_test_app/spec-opal/active-record/instance_methods_spec.rb +53 -0
  351. data/reactive_record_test_app/spec-opal/active-record/non_ar_aggregations_spec.rb +74 -0
  352. data/reactive_record_test_app/spec-opal/active-record/permissions_spec.rb +170 -0
  353. data/reactive_record_test_app/spec-opal/active-record/prerendering_spec.rb +49 -0
  354. data/reactive_record_test_app/spec-opal/active-record/reactive_record_load_spec.rb +23 -0
  355. data/reactive_record_test_app/spec-opal/active-record/rendering_spec.rb +221 -0
  356. data/reactive_record_test_app/spec-opal/active-record/save_spec.rb +125 -0
  357. data/reactive_record_test_app/spec-opal/active-record/scope_spec.rb +85 -0
  358. data/reactive_record_test_app/spec-opal/active-record/update_aggregations_spec.rb +76 -0
  359. data/reactive_record_test_app/spec-opal/active-record/update_attributes_spec.rb +186 -0
  360. data/reactive_record_test_app/spec-opal/active-record/virtual_methods_spec.rb +71 -0
  361. data/reactive_record_test_app/spec-opal/index.html.erb +11 -0
  362. data/reactive_record_test_app/spec-opal/spec_helper.js.rb +268 -0
  363. data/reactive_record_test_app/spec-opal/vendor/es5-shim.min.js +6 -0
  364. data/reactive_record_test_app/spec_dont_run/README.md +26 -0
  365. data/reactive_record_test_app/spec_dont_run/moved_to_main_spec_dir/zzzmany_to_many_spec_moved_to_main_suite.rb +30 -0
  366. data/reactive_record_test_app/spec_dont_run/moved_to_main_spec_dir/zzzrevert_record_spec_moved.rb +78 -0
  367. data/reactive_record_test_app/spec_dont_run/moved_to_main_spec_dir/zzzupdate_associations_spec_moved.rb +142 -0
  368. data/reactive_record_test_app/spec_dont_run/moved_to_main_spec_dir/zzzupdate_scopes_movedspec.rb +48 -0
  369. data/remote.md +115 -0
  370. data/spec/bin/firebug-2.0.13-fx.xpi +0 -0
  371. data/spec/component_helpers_xspec.rb +49 -0
  372. data/spec/factories/child_model.rb +5 -0
  373. data/spec/factories/comment.rb +5 -0
  374. data/spec/factories/test_models.rb +5 -0
  375. data/spec/factories/todo.rb +5 -0
  376. data/spec/factories/user.rb +5 -0
  377. data/spec/reactive_record/edge_cases_spec.rb +31 -0
  378. data/spec/reactive_record/factory.rb +62 -0
  379. data/spec/reactive_record/many_to_many_spec.rb +50 -0
  380. data/spec/reactive_record/play.rb +64 -0
  381. data/spec/reactive_record/pry_rescue_xspec.rb +48 -0
  382. data/spec/reactive_record/revert_spec.rb +112 -0
  383. data/spec/reactive_record/update_associations_spec.rb +189 -0
  384. data/spec/reactive_record/update_scopes_spec.rb +53 -0
  385. data/spec/spec_helper.rb +366 -0
  386. data/spec/support/component_helpers.rb +351 -0
  387. data/spec/synchromesh/column_types/column_type_spec.rb +302 -0
  388. data/spec/synchromesh/connection_spec.rb +144 -0
  389. data/spec/synchromesh/crud_access_regulation/broadcast_controls_access_spec.rb +105 -0
  390. data/spec/synchromesh/crud_access_regulation/model_policies_spec.rb +131 -0
  391. data/spec/synchromesh/examples/dictionary.rb +239 -0
  392. data/spec/synchromesh/examples/dictionary_with_client_scopes.rb +196 -0
  393. data/spec/synchromesh/examples/random_examples.rb +100 -0
  394. data/spec/synchromesh/examples/scoped_todos_spec.rb +167 -0
  395. data/spec/synchromesh/integration/authorization_spec.rb +111 -0
  396. data/spec/synchromesh/integration/default_scope_spec.rb +121 -0
  397. data/spec/synchromesh/integration/has_many_through_spec.rb +173 -0
  398. data/spec/synchromesh/integration/relationships_spec.rb +263 -0
  399. data/spec/synchromesh/integration/scope_spec.rb +553 -0
  400. data/spec/synchromesh/integration/synchromesh_spec.rb +80 -0
  401. data/spec/synchromesh/integration/test_components.rb +18 -0
  402. data/spec/synchromesh/integration/transports_spec.rb +308 -0
  403. data/spec/synchromesh/policies/auto_connect_spec.rb +60 -0
  404. data/spec/synchromesh/policies/auto_loader_spec.rb +34 -0
  405. data/spec/synchromesh/policies/policy_methods_spec.rb +85 -0
  406. data/spec/synchromesh/policies/regulate_all_broadcasts_spec.rb +315 -0
  407. data/spec/synchromesh/policies/regulate_broadcast_spec.rb +370 -0
  408. data/spec/synchromesh/policies/regulate_class_connection_spec.rb +50 -0
  409. data/spec/synchromesh/policies/regulate_instance_connection_spec.rb +66 -0
  410. data/spec/test_app/Gemfile +61 -0
  411. data/spec/test_app/Gemfile.lock +253 -0
  412. data/spec/test_app/Rakefile +6 -0
  413. data/spec/test_app/app/assets/javascripts/application.js +6 -0
  414. data/spec/test_app/app/assets/stylesheets/application.css +15 -0
  415. data/spec/test_app/app/controllers/application_controller.rb +13 -0
  416. data/spec/test_app/app/controllers/test_controller.rb +5 -0
  417. data/spec/test_app/app/models/_react_public_models.rb +2 -0
  418. data/spec/test_app/app/models/public/address.rb +13 -0
  419. data/spec/test_app/app/models/public/child_model.rb +3 -0
  420. data/spec/test_app/app/models/public/comment.rb +25 -0
  421. data/spec/test_app/app/models/public/test_model.rb +5 -0
  422. data/spec/test_app/app/models/public/todo.rb +6 -0
  423. data/spec/test_app/app/models/public/todo_item.rb +36 -0
  424. data/spec/test_app/app/models/public/user.rb +88 -0
  425. data/spec/test_app/app/policies/auto_loader_test_classa_policy.rb +3 -0
  426. data/spec/test_app/app/policies/auto_loader_test_classb_policy.rb +3 -0
  427. data/spec/test_app/app/policies/auto_loader_test_classc_policy.rb +3 -0
  428. data/spec/test_app/app/policies/auto_loader_test_classd_policy.rb +3 -0
  429. data/spec/test_app/app/views/components.rb +14 -0
  430. data/spec/test_app/app/views/components/show.rb +5 -0
  431. data/spec/test_app/app/views/layouts/application.html.erb +14 -0
  432. data/spec/test_app/bin/bundle +3 -0
  433. data/spec/test_app/bin/rails +4 -0
  434. data/spec/test_app/bin/rake +4 -0
  435. data/spec/test_app/bin/setup +29 -0
  436. data/spec/test_app/config.ru +4 -0
  437. data/spec/test_app/config/application.rb +42 -0
  438. data/spec/test_app/config/boot.rb +6 -0
  439. data/spec/test_app/config/cable.yml +10 -0
  440. data/spec/test_app/config/database.yml +47 -0
  441. data/spec/test_app/config/environment.rb +5 -0
  442. data/spec/test_app/config/environments/development.rb +41 -0
  443. data/spec/test_app/config/environments/production.rb +79 -0
  444. data/spec/test_app/config/environments/test.rb +42 -0
  445. data/spec/test_app/config/initializers/assets.rb +11 -0
  446. data/spec/test_app/config/initializers/backtrace_silencers.rb +7 -0
  447. data/spec/test_app/config/initializers/cookies_serializer.rb +3 -0
  448. data/spec/test_app/config/initializers/filter_parameter_logging.rb +4 -0
  449. data/spec/test_app/config/initializers/inflections.rb +16 -0
  450. data/spec/test_app/config/initializers/mime_types.rb +4 -0
  451. data/spec/test_app/config/initializers/session_store.rb +3 -0
  452. data/spec/test_app/config/initializers/synchromesh.rb +11 -0
  453. data/spec/test_app/config/initializers/wrap_parameters.rb +14 -0
  454. data/spec/test_app/config/locales/en.yml +23 -0
  455. data/spec/test_app/config/routes.rb +61 -0
  456. data/spec/test_app/config/secrets.yml +22 -0
  457. data/spec/test_app/db/development.sqlite3 +0 -0
  458. data/spec/test_app/db/migrate/20160731182106_create_test_models.rb +75 -0
  459. data/spec/test_app/db/schema.rb +88 -0
  460. data/spec/test_app/db/seeds.rb +7 -0
  461. data/spec/test_app/lib/assets/.keep +0 -0
  462. data/spec/test_app/log/.keep +0 -0
  463. data/spec/test_app/public/404.html +67 -0
  464. data/spec/test_app/public/422.html +67 -0
  465. data/spec/test_app/public/500.html +66 -0
  466. data/spec/test_app/public/favicon.ico +0 -0
  467. data/spec/vendor/es5-shim.min.js +6 -0
  468. data/terminal.md +66 -0
  469. metadata +1175 -0
@@ -0,0 +1,517 @@
1
+ module ReactiveRecord
2
+
3
+ class Collection
4
+
5
+ class DummySet
6
+ def new
7
+ @master ||= super
8
+ end
9
+ def method_missing(*args)
10
+ end
11
+ end
12
+
13
+ def unsaved_children
14
+ old_uc_already_being_called = @uc_already_being_called
15
+ if @owner && @association
16
+ @unsaved_children ||= Set.new
17
+ unless @uc_already_being_called
18
+ @uc_already_being_called = true
19
+ #@owner.backing_record.update_attribute(@association.attribute)
20
+ end
21
+ else
22
+ @unsaved_children ||= DummySet.new
23
+ end
24
+ @unsaved_children
25
+ ensure
26
+ @uc_already_being_called = old_uc_already_being_called
27
+ end
28
+
29
+ def initialize(target_klass, owner = nil, association = nil, *vector)
30
+ @owner = owner # can be nil if this is an outer most scope
31
+ @association = association
32
+ @target_klass = target_klass
33
+ if owner and !owner.id and vector.length <= 1
34
+ @collection = []
35
+ elsif vector.length > 0
36
+ @vector = vector
37
+ elsif owner
38
+ @vector = owner.backing_record.vector + [association.attribute]
39
+ else
40
+ @vector = [target_klass]
41
+ end
42
+ @scopes = {}
43
+ end
44
+
45
+ def dup_for_sync
46
+ self.dup.instance_eval do
47
+ @collection = @collection.dup if @collection
48
+ @scopes = @scopes.dup
49
+ self
50
+ end
51
+ end
52
+
53
+ def all
54
+ observed
55
+ @dummy_collection.notify if @dummy_collection
56
+ unless @collection
57
+ @collection = []
58
+ if ids = ReactiveRecord::Base.fetch_from_db([*@vector, "*all"])
59
+ ids.each do |id|
60
+ @collection << @target_klass.find_by(@target_klass.primary_key => id)
61
+ end
62
+ else
63
+ @dummy_collection = ReactiveRecord::Base.load_from_db(nil, *@vector, "*all")
64
+ @dummy_record = self[0]
65
+ end
66
+ end
67
+ @collection
68
+ end
69
+
70
+ def [](index)
71
+ observed
72
+ if (@collection || all).length <= index and @dummy_collection
73
+ (@collection.length..index).each do |i|
74
+ new_dummy_record = ReactiveRecord::Base.new_from_vector(@target_klass, nil, *@vector, "*#{i}")
75
+ new_dummy_record.backing_record.attributes[@association.inverse_of] = @owner if @association && !@association.through_association?
76
+ @collection << new_dummy_record
77
+ end
78
+ end
79
+ @collection[index]
80
+ end
81
+
82
+ def ==(other_collection)
83
+ observed
84
+ return !@collection unless other_collection.is_a? Collection
85
+ other_collection.observed
86
+ my_children = (@collection || []).select { |target| target != @dummy_record }
87
+ if other_collection
88
+ other_children = (other_collection.collection || []).select { |target| target != other_collection.dummy_record }
89
+ return false unless my_children == other_children
90
+ unsaved_children.to_a == other_collection.unsaved_children.to_a
91
+ else
92
+ my_children.empty? && unsaved_children.empty?
93
+ end
94
+ end
95
+ # todo move following to a separate module related to scope updates ******************
96
+ attr_reader :vector
97
+ attr_writer :scope_description
98
+ attr_writer :parent
99
+ attr_reader :pre_sync_related_records
100
+
101
+ def to_s
102
+ "<Coll-#{object_id} - #{vector}>"
103
+ end
104
+
105
+ class << self
106
+ def sync_scopes(broadcast)
107
+ # record_with_current_values will return nil if data between
108
+ # the broadcast record and the value on the client is out of sync
109
+ # not running set_pre_sync_related_records will cause sync scopes
110
+ # to refresh all related scopes
111
+ React::State.bulk_update do
112
+ record = broadcast.record_with_current_values
113
+ apply_to_all_collections(
114
+ :set_pre_sync_related_records,
115
+ record, broadcast.new?
116
+ ) if record
117
+ record = broadcast.record_with_new_values
118
+ apply_to_all_collections(
119
+ :sync_scopes,
120
+ record, record.destroyed?
121
+ )
122
+ record.backing_record.sync_unscoped_collection! if record.destroyed? || broadcast.new?
123
+ end
124
+ end
125
+
126
+ def apply_to_all_collections(method, record, dont_gather)
127
+ related_records = Set.new if dont_gather
128
+ Base.outer_scopes.each do |collection|
129
+ unless dont_gather
130
+ related_records = collection.gather_related_records(record)
131
+ end
132
+ collection.send method, related_records, record
133
+ end
134
+ end
135
+ end
136
+
137
+ def gather_related_records(record, related_records = Set.new)
138
+ merge_related_records(record, related_records)
139
+ live_scopes.each do |collection|
140
+ collection.gather_related_records(record, related_records)
141
+ end
142
+ related_records
143
+ end
144
+
145
+ def merge_related_records(record, related_records)
146
+ if filter? && joins_with?(record)
147
+ related_records.merge(related_records_for(record))
148
+ end
149
+ related_records
150
+ end
151
+
152
+ def filter?
153
+ true
154
+ end
155
+
156
+ # is it necessary to check @association in the next 2 methods???
157
+
158
+ def joins_with?(record)
159
+ if @association && @association.through_association
160
+ @association.through_association.klass == record.class
161
+ else
162
+ @target_klass == record.class
163
+ end
164
+ end
165
+
166
+ def related_records_for(record)
167
+ return [] unless @association
168
+ attrs = record.backing_record.attributes
169
+ return [] unless attrs[@association.inverse_of] == @owner
170
+ if !@association.through_association
171
+ [record]
172
+ elsif (source = attrs[@association.source])
173
+ [source]
174
+ else
175
+ []
176
+ end
177
+ end
178
+
179
+ def collector?
180
+ false
181
+ end
182
+
183
+ def filter_records(related_records)
184
+ # possibly we should never get here???
185
+ scope_args = @vector.last.is_a?(Array) ? @vector.last[1..-1] : []
186
+ @scope_description.filter_records(related_records, scope_args)
187
+ end
188
+
189
+ def live_scopes
190
+ @live_scopes ||= Set.new
191
+ end
192
+
193
+ def set_pre_sync_related_records(related_records, _record = nil)
194
+ #related_records = related_records.intersection([*@collection]) <- deleting this works
195
+ @pre_sync_related_records = related_records #in_this_collection related_records <- not sure if this works
196
+ live_scopes.each { |scope| scope.set_pre_sync_related_records(@pre_sync_related_records) }
197
+ end
198
+
199
+ def sync_scopes(related_records, record, filtering = true)
200
+ #related_records = related_records.intersection([*@collection])
201
+ #related_records = in_this_collection related_records
202
+ live_scopes.each { |scope| scope.sync_scopes(related_records, record, filtering) }
203
+ notify_of_change unless related_records.empty?
204
+ ensure
205
+ @pre_sync_related_records = nil
206
+ end
207
+
208
+ # def in_this_collection(related_records)
209
+ # related_records.delete_if do |r|
210
+ # # BELOW IS WRONG... its more complicated isn't it...
211
+ # if @association.through_association
212
+ #
213
+ # else
214
+ # r.backing_record.attributes[@association.inverse_of] != @owner
215
+ # end
216
+ # end
217
+
218
+ def apply_scope(name, *vector)
219
+ build_child_scope(ScopeDescription.find(@target_klass, name), *name, *vector)
220
+ end
221
+
222
+ def child_scopes
223
+ @child_scopes ||= {}
224
+ end
225
+
226
+ def build_child_scope(scope_description, *scope_vector)
227
+ child_scopes[scope_vector] ||= begin
228
+ new_vector = @vector
229
+ new_vector += [scope_vector] unless new_vector.nil? || scope_vector.empty?
230
+ child_scope = Collection.new(@target_klass, nil, nil, *new_vector)
231
+ child_scope.scope_description = scope_description
232
+ child_scope.parent = self
233
+ child_scope.extend ScopedCollection
234
+ child_scope
235
+ end
236
+ end
237
+
238
+ def link_to_parent
239
+ return if @linked
240
+ @linked = true
241
+ if @parent
242
+ @parent.link_child self
243
+ sync_collection_with_parent unless collection
244
+ else
245
+ ReactiveRecord::Base.add_to_outer_scopes self
246
+ end
247
+ all if collector? # force fetch all so the collector can do its job
248
+ end
249
+
250
+ def link_child(child)
251
+ live_scopes << child
252
+ link_to_parent
253
+ end
254
+
255
+ def sync_collection_with_parent
256
+ if @parent.collection
257
+ if @parent.collection.empty?
258
+ @collection = []
259
+ elsif filter?
260
+ @collection = filter_records(@parent.collection)
261
+ end
262
+ elsif @parent.count.zero?
263
+ @count = 0
264
+ end
265
+ end
266
+
267
+ # end of stuff to move
268
+
269
+ def reload_from_db(force = nil)
270
+ if force || React::State.has_observers?(self, :collection)
271
+ @out_of_date = false
272
+ ReactiveRecord::Base.load_from_db(nil, *@vector, '*all') if @collection
273
+ ReactiveRecord::Base.load_from_db(nil, *@vector, '*count')
274
+ else
275
+ @out_of_date = true
276
+ end
277
+ self
278
+ end
279
+
280
+ def observed
281
+ return if @observing || ReactiveRecord::Base.data_loading?
282
+ begin
283
+ @observing = true
284
+ link_to_parent
285
+ reload_from_db(true) if @out_of_date
286
+ React::State.get_state(self, :collection)
287
+ ensure
288
+ @observing = false
289
+ end
290
+ end
291
+
292
+ def set_count_state(val)
293
+ unless ReactiveRecord::WhileLoading.has_observers?
294
+ React::State.set_state(self, :collection, collection, true)
295
+ end
296
+ @count = val
297
+ end
298
+
299
+ def count
300
+ observed
301
+ if @collection
302
+ @collection.count
303
+ elsif @count ||= ReactiveRecord::Base.fetch_from_db([*@vector, "*count"])
304
+ @count
305
+ else
306
+ ReactiveRecord::Base.load_from_db(nil, *@vector, "*count")
307
+ @count = 1
308
+ end
309
+ end
310
+
311
+ alias_method :length, :count
312
+
313
+ # WHY IS THIS NEEDED? Perhaps it was just for debug
314
+ def collect(*args, &block)
315
+ all.collect(*args, &block)
316
+ end
317
+
318
+ # def each_known_child
319
+ # [*collection, *client_pushes].each { |i| yield i }
320
+ # end
321
+
322
+ def proxy_association
323
+ @association || self # returning self allows this to work with things like Model.all
324
+ end
325
+
326
+ def klass
327
+ @target_klass
328
+ end
329
+
330
+ def push_and_update_belongs_to(id)
331
+ # example collection vector: TestModel.find(1).child_models.harrybarry
332
+ # harrybarry << child means that
333
+ # child.test_model = 1
334
+ # so... we go back starting at this collection and look for the first
335
+ # collection with an owner... that is our guy
336
+ child = proxy_association.klass.find(id)
337
+ push child
338
+ set_belongs_to child
339
+ end
340
+
341
+ def set_belongs_to(child)
342
+ if @owner
343
+ child.send("#{@association.inverse_of}=", @owner) if @association
344
+ elsif @parent
345
+ @parent.set_belongs_to(child)
346
+ end
347
+ child
348
+ end
349
+
350
+ attr_reader :client_collection
351
+
352
+ # appointment.doctor = doctor_value (i.e. through association is changing)
353
+ # means appointment.doctor_value.patients << appointment.patient
354
+ # and we have to appointment.doctor(current value).patients.delete(appointment.patient)
355
+
356
+
357
+ def update_child(item)
358
+ backing_record = item.backing_record
359
+ if backing_record && @owner && @association && !@association.through_association? && item.attributes[@association.inverse_of] != @owner
360
+ inverse_of = @association.inverse_of
361
+ current_association = item.attributes[inverse_of]
362
+ backing_record.virgin = false unless backing_record.data_loading?
363
+ backing_record.update_attribute(inverse_of, @owner)
364
+ current_association.attributes[@association.attribute].delete(item) if current_association and current_association.attributes[@association.attribute]
365
+ @owner.backing_record.update_attribute(@association.attribute) # forces a check if association contents have changed from synced values
366
+ end
367
+ end
368
+
369
+ def push(item)
370
+ if collection
371
+ self.force_push item
372
+ else
373
+ unsaved_children << item
374
+ update_child(item)
375
+ @owner.backing_record.update_attribute(@association.attribute) if @owner && @association
376
+ if !@count.nil?
377
+ @count += item.destroyed? ? -1 : 1
378
+ notify_of_change self
379
+ end
380
+ end
381
+ self
382
+ end
383
+
384
+ alias << push
385
+
386
+ def sort!(*args, &block)
387
+ replace(sort(*args, &block))
388
+ end
389
+
390
+ def force_push(item)
391
+ return delete(item) if item.destroyed? # pushing a destroyed item is the same as removing it
392
+ all << item unless all.include? item # does this use == if so we are okay...
393
+ update_child(item)
394
+ if item.id and @dummy_record
395
+ @dummy_record.id = item.id
396
+ # we cant use == because that just means the objects are referencing
397
+ # the same backing record.
398
+ @collection.reject { |i| i.object_id == @dummy_record.object_id }
399
+ @dummy_record = @collection.detect { |r| r.backing_record.vector.last =~ /^\*[0-9]+$/ }
400
+ @dummy_collection = nil
401
+ end
402
+ notify_of_change self
403
+ end
404
+
405
+ [:first, :last].each do |method|
406
+ define_method method do |*args|
407
+ if args.count == 0
408
+ all.send(method)
409
+ else
410
+ apply_scope(method, *args)
411
+ end
412
+ end
413
+ end
414
+
415
+ def replace(new_array)
416
+ unsaved_children.clear
417
+ new_array = new_array.to_a
418
+ return self if new_array == @collection
419
+ Base.load_data { internal_replace(new_array) }
420
+ notify_of_change new_array
421
+ end
422
+
423
+ def internal_replace(new_array)
424
+
425
+ # not tested if you do all[n] where n > 0... this will create additional dummy items, that this will not sync up.
426
+ # probably just moving things around so the @dummy_collection and @dummy_record are updated AFTER the new items are pushed
427
+ # should work.
428
+
429
+ if @dummy_collection
430
+ @dummy_collection.notify
431
+ array = new_array.is_a?(Collection) ? new_array.collection : new_array
432
+ @collection.each_with_index do |r, i|
433
+ r.id = new_array[i].id if array[i] and array[i].id and !r.new? and r.backing_record.vector.last =~ /^\*[0-9]+$/
434
+ end
435
+ end
436
+
437
+ @collection.dup.each { |item| delete(item) } if @collection # this line is a big nop I think
438
+ @collection = []
439
+ if new_array.is_a? Collection
440
+ @dummy_collection = new_array.dummy_collection
441
+ @dummy_record = new_array.dummy_record
442
+ new_array.collection.each { |item| self << item } if new_array.collection
443
+ else
444
+ @dummy_collection = @dummy_record = nil
445
+ new_array.each { |item| self << item }
446
+ end
447
+ notify_of_change new_array
448
+ end
449
+
450
+ def delete(item)
451
+ unsaved_children.delete(item)
452
+ notify_of_change(
453
+ if @owner && @association && !@association.through_association?
454
+ inverse_of = @association.inverse_of
455
+ if (backing_record = item.backing_record) && backing_record.attributes[inverse_of] == @owner
456
+ # the if prevents double update if delete is being called from << (see << above)
457
+ backing_record.update_attribute(inverse_of, nil)
458
+ end
459
+ # forces a check if association contents have changed from synced values
460
+ delete_internal(item) { @owner.backing_record.update_attribute(@association.attribute) }
461
+ else
462
+ delete_internal(item)
463
+ end
464
+ )
465
+ end
466
+
467
+ def delete_internal(item)
468
+ if collection
469
+ all.delete(item)
470
+ elsif !@count.nil?
471
+ @count -= 1
472
+ end
473
+ yield item if block_given?
474
+ item
475
+ end
476
+
477
+ def loading?
478
+ all # need to force initialization at this point
479
+ @dummy_collection.loading?
480
+ end
481
+
482
+ def empty? # should be handled by method missing below, but opal-rspec does not deal well with method missing, so to test...
483
+ all.empty?
484
+ end
485
+
486
+ def method_missing(method, *args, &block)
487
+ if [].respond_to? method
488
+ all.send(method, *args, &block)
489
+ elsif @target_klass.respond_to?(method) or (args.count == 1 && method =~ /^find_by_/)
490
+ apply_scope(method, *args)
491
+ else
492
+ super
493
+ end
494
+ end
495
+
496
+ protected
497
+
498
+ def dummy_record
499
+ @dummy_record
500
+ end
501
+
502
+ def collection
503
+ @collection
504
+ end
505
+
506
+ def dummy_collection
507
+ @dummy_collection
508
+ end
509
+
510
+ def notify_of_change(value = nil)
511
+ React::State.set_state(self, "collection", collection) unless ReactiveRecord::Base.data_loading?
512
+ value
513
+ end
514
+
515
+ end
516
+
517
+ end