hyper-mesh 0.4.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 (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