hyper-mesh 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +27 -0
- data/.rspec +2 -0
- data/.rubocop.yml +11 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +396 -0
- data/Rakefile +6 -0
- data/app/controllers/reactive_record/application_controller.rb +4 -0
- data/app/controllers/reactive_record/reactive_record_controller.rb +49 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/codeship.database.yml +18 -0
- data/config/routes.rb +7 -0
- data/docs/action_cable_quickstart.md +151 -0
- data/docs/authorization-policies.md +449 -0
- data/docs/client_side_scoping.md +103 -0
- data/docs/pusher_quickstart.md +0 -0
- data/docs/simple_poller_quickstart.md +121 -0
- data/docs/todo-example.md +116 -0
- data/docs/words-example.md +65 -0
- data/examples/action-cable/.gitignore +21 -0
- data/examples/action-cable/Gemfile +58 -0
- data/examples/action-cable/Gemfile.lock +247 -0
- data/examples/action-cable/README.md +24 -0
- data/examples/action-cable/Rakefile +6 -0
- data/examples/action-cable/app/assets/config/manifest.js +3 -0
- data/examples/action-cable/app/assets/javascripts/application.js +18 -0
- data/examples/action-cable/app/assets/stylesheets/application.css +15 -0
- data/examples/action-cable/app/controllers/application_controller.rb +3 -0
- data/examples/action-cable/app/controllers/test_controller.rb +6 -0
- data/examples/action-cable/app/models/models.rb +2 -0
- data/examples/action-cable/app/models/public/application_record.rb +3 -0
- data/examples/action-cable/app/models/public/word.rb +2 -0
- data/examples/action-cable/app/policies/application_policy.rb +6 -0
- data/examples/action-cable/app/views/components.rb +17 -0
- data/examples/action-cable/app/views/components/app.rb +18 -0
- data/examples/action-cable/app/views/layouts/application.html.erb +14 -0
- data/examples/action-cable/app/views/layouts/mailer.html.erb +13 -0
- data/examples/action-cable/app/views/layouts/mailer.text.erb +1 -0
- data/examples/action-cable/bin/bundle +3 -0
- data/examples/action-cable/bin/rails +9 -0
- data/examples/action-cable/bin/rake +9 -0
- data/examples/action-cable/bin/setup +34 -0
- data/examples/action-cable/bin/spring +15 -0
- data/examples/action-cable/bin/update +29 -0
- data/examples/action-cable/config.ru +5 -0
- data/examples/action-cable/config/application.rb +30 -0
- data/examples/action-cable/config/boot.rb +3 -0
- data/examples/action-cable/config/cable.yml +9 -0
- data/examples/action-cable/config/database.yml +25 -0
- data/examples/action-cable/config/environment.rb +5 -0
- data/examples/action-cable/config/environments/development.rb +45 -0
- data/examples/action-cable/config/environments/production.rb +86 -0
- data/examples/action-cable/config/environments/test.rb +42 -0
- data/examples/action-cable/config/initializers/application_controller_renderer.rb +6 -0
- data/examples/action-cable/config/initializers/assets.rb +11 -0
- data/examples/action-cable/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/action-cable/config/initializers/cookies_serializer.rb +5 -0
- data/examples/action-cable/config/initializers/filter_parameter_logging.rb +4 -0
- data/examples/action-cable/config/initializers/inflections.rb +16 -0
- data/examples/action-cable/config/initializers/mime_types.rb +4 -0
- data/examples/action-cable/config/initializers/new_framework_defaults.rb +24 -0
- data/examples/action-cable/config/initializers/session_store.rb +3 -0
- data/examples/action-cable/config/initializers/synchromesh.rb +5 -0
- data/examples/action-cable/config/initializers/wrap_parameters.rb +14 -0
- data/examples/action-cable/config/locales/en.yml +23 -0
- data/examples/action-cable/config/puma.rb +47 -0
- data/examples/action-cable/config/routes.rb +5 -0
- data/examples/action-cable/config/secrets.yml +22 -0
- data/examples/action-cable/config/spring.rb +6 -0
- data/examples/action-cable/db/migrate/20160921223808_create_words.rb +9 -0
- data/examples/action-cable/db/schema.rb +21 -0
- data/examples/action-cable/log/.keep +0 -0
- data/examples/action-cable/public/404.html +67 -0
- data/examples/action-cable/public/422.html +67 -0
- data/examples/action-cable/public/500.html +66 -0
- data/examples/action-cable/public/apple-touch-icon-precomposed.png +0 -0
- data/examples/action-cable/public/apple-touch-icon.png +0 -0
- data/examples/action-cable/public/favicon.ico +0 -0
- data/examples/action-cable/public/robots.txt +5 -0
- data/examples/action-cable/rails_cache_dir2/C91/480/synchromesh_active_connections +0 -0
- data/examples/action-cable/tmp/.keep +0 -0
- data/examples/action-cable/vendor/assets/javascripts/.keep +0 -0
- data/examples/action-cable/vendor/assets/stylesheets/.keep +0 -0
- data/examples/simple-poller/.gitignore +21 -0
- data/examples/simple-poller/Gemfile +64 -0
- data/examples/simple-poller/Gemfile.lock +272 -0
- data/examples/simple-poller/README.md +24 -0
- data/examples/simple-poller/Rakefile +6 -0
- data/examples/simple-poller/app/assets/config/manifest.js +3 -0
- data/examples/simple-poller/app/assets/images/.keep +0 -0
- data/examples/simple-poller/app/assets/javascripts/application.js +20 -0
- data/examples/simple-poller/app/assets/javascripts/channels/.keep +0 -0
- data/examples/simple-poller/app/assets/stylesheets/application.css +15 -0
- data/examples/simple-poller/app/channels/application_cable/channel.rb +4 -0
- data/examples/simple-poller/app/channels/application_cable/connection.rb +4 -0
- data/examples/simple-poller/app/controllers/application_controller.rb +3 -0
- data/examples/simple-poller/app/controllers/concerns/.keep +0 -0
- data/examples/simple-poller/app/controllers/test_controller.rb +6 -0
- data/examples/simple-poller/app/helpers/application_helper.rb +2 -0
- data/examples/simple-poller/app/jobs/application_job.rb +2 -0
- data/examples/simple-poller/app/mailers/application_mailer.rb +4 -0
- data/examples/simple-poller/app/models/concerns/.keep +0 -0
- data/examples/simple-poller/app/models/models.rb +2 -0
- data/examples/simple-poller/app/models/public/.keep +0 -0
- data/examples/simple-poller/app/models/public/application_record.rb +3 -0
- data/examples/simple-poller/app/models/public/word.rb +2 -0
- data/examples/simple-poller/app/policies/application_policy.rb +5 -0
- data/examples/simple-poller/app/views/components.rb +18 -0
- data/examples/simple-poller/app/views/components/.keep +0 -0
- data/examples/simple-poller/app/views/components/app.rb +40 -0
- data/examples/simple-poller/app/views/layouts/application.html.erb +14 -0
- data/examples/simple-poller/app/views/layouts/mailer.html.erb +13 -0
- data/examples/simple-poller/app/views/layouts/mailer.text.erb +1 -0
- data/examples/simple-poller/bin/bundle +3 -0
- data/examples/simple-poller/bin/rails +9 -0
- data/examples/simple-poller/bin/rake +9 -0
- data/examples/simple-poller/bin/setup +34 -0
- data/examples/simple-poller/bin/spring +16 -0
- data/examples/simple-poller/bin/update +29 -0
- data/examples/simple-poller/config.ru +5 -0
- data/examples/simple-poller/config/application.rb +20 -0
- data/examples/simple-poller/config/boot.rb +3 -0
- data/examples/simple-poller/config/cable.yml +9 -0
- data/examples/simple-poller/config/database.yml +25 -0
- data/examples/simple-poller/config/environment.rb +5 -0
- data/examples/simple-poller/config/environments/development.rb +44 -0
- data/examples/simple-poller/config/environments/production.rb +86 -0
- data/examples/simple-poller/config/environments/test.rb +42 -0
- data/examples/simple-poller/config/initializers/application_controller_renderer.rb +6 -0
- data/examples/simple-poller/config/initializers/assets.rb +11 -0
- data/examples/simple-poller/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/simple-poller/config/initializers/cookies_serializer.rb +5 -0
- data/examples/simple-poller/config/initializers/filter_parameter_logging.rb +4 -0
- data/examples/simple-poller/config/initializers/inflections.rb +16 -0
- data/examples/simple-poller/config/initializers/mime_types.rb +4 -0
- data/examples/simple-poller/config/initializers/new_framework_defaults.rb +24 -0
- data/examples/simple-poller/config/initializers/session_store.rb +3 -0
- data/examples/simple-poller/config/initializers/synchromesh.rb +15 -0
- data/examples/simple-poller/config/initializers/wrap_parameters.rb +14 -0
- data/examples/simple-poller/config/locales/en.yml +23 -0
- data/examples/simple-poller/config/puma.rb +47 -0
- data/examples/simple-poller/config/routes.rb +5 -0
- data/examples/simple-poller/config/secrets.yml +22 -0
- data/examples/simple-poller/config/spring.rb +6 -0
- data/examples/simple-poller/db/migrate/20161013220135_create_words.rb +9 -0
- data/examples/simple-poller/db/schema.rb +21 -0
- data/examples/simple-poller/db/seeds.rb +7 -0
- data/examples/simple-poller/lib/assets/.keep +0 -0
- data/examples/simple-poller/lib/tasks/.keep +0 -0
- data/examples/simple-poller/log/.keep +0 -0
- data/examples/simple-poller/public/404.html +67 -0
- data/examples/simple-poller/public/422.html +67 -0
- data/examples/simple-poller/public/500.html +66 -0
- data/examples/simple-poller/public/apple-touch-icon-precomposed.png +0 -0
- data/examples/simple-poller/public/apple-touch-icon.png +0 -0
- data/examples/simple-poller/public/favicon.ico +0 -0
- data/examples/simple-poller/public/robots.txt +5 -0
- data/examples/simple-poller/test/controllers/.keep +0 -0
- data/examples/simple-poller/test/fixtures/.keep +0 -0
- data/examples/simple-poller/test/fixtures/files/.keep +0 -0
- data/examples/simple-poller/test/fixtures/words.yml +7 -0
- data/examples/simple-poller/test/helpers/.keep +0 -0
- data/examples/simple-poller/test/integration/.keep +0 -0
- data/examples/simple-poller/test/mailers/.keep +0 -0
- data/examples/simple-poller/test/models/.keep +0 -0
- data/examples/simple-poller/test/models/word_test.rb +7 -0
- data/examples/simple-poller/test/test_helper.rb +10 -0
- data/examples/simple-poller/tmp/.keep +0 -0
- data/examples/simple-poller/vendor/assets/javascripts/.keep +0 -0
- data/examples/simple-poller/vendor/assets/stylesheets/.keep +0 -0
- data/examples/words/.gitignore +21 -0
- data/examples/words/Gemfile +58 -0
- data/examples/words/Gemfile.lock +247 -0
- data/examples/words/README.md +24 -0
- data/examples/words/Rakefile +6 -0
- data/examples/words/app/assets/config/manifest.js +3 -0
- data/examples/words/app/assets/javascripts/application.js +18 -0
- data/examples/words/app/assets/stylesheets/application.css +15 -0
- data/examples/words/app/controllers/application_controller.rb +3 -0
- data/examples/words/app/controllers/test_controller.rb +6 -0
- data/examples/words/app/models/models.rb +2 -0
- data/examples/words/app/models/public/application_record.rb +3 -0
- data/examples/words/app/models/public/word.rb +10 -0
- data/examples/words/app/policies/application_policy.rb +6 -0
- data/examples/words/app/views/components.rb +16 -0
- data/examples/words/app/views/components/app.rb +31 -0
- data/examples/words/app/views/layouts/application.html.erb +14 -0
- data/examples/words/app/views/layouts/mailer.html.erb +13 -0
- data/examples/words/app/views/layouts/mailer.text.erb +1 -0
- data/examples/words/bin/bundle +3 -0
- data/examples/words/bin/rails +9 -0
- data/examples/words/bin/rake +9 -0
- data/examples/words/bin/setup +34 -0
- data/examples/words/bin/spring +15 -0
- data/examples/words/bin/update +29 -0
- data/examples/words/config.ru +5 -0
- data/examples/words/config/application.rb +30 -0
- data/examples/words/config/boot.rb +3 -0
- data/examples/words/config/cable.yml +9 -0
- data/examples/words/config/database.yml +25 -0
- data/examples/words/config/environment.rb +5 -0
- data/examples/words/config/environments/development.rb +45 -0
- data/examples/words/config/environments/production.rb +86 -0
- data/examples/words/config/environments/test.rb +42 -0
- data/examples/words/config/initializers/application_controller_renderer.rb +6 -0
- data/examples/words/config/initializers/assets.rb +11 -0
- data/examples/words/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/words/config/initializers/cookies_serializer.rb +5 -0
- data/examples/words/config/initializers/filter_parameter_logging.rb +4 -0
- data/examples/words/config/initializers/inflections.rb +16 -0
- data/examples/words/config/initializers/mime_types.rb +4 -0
- data/examples/words/config/initializers/new_framework_defaults.rb +24 -0
- data/examples/words/config/initializers/session_store.rb +3 -0
- data/examples/words/config/initializers/synchromesh.rb +5 -0
- data/examples/words/config/initializers/wrap_parameters.rb +14 -0
- data/examples/words/config/locales/en.yml +23 -0
- data/examples/words/config/puma.rb +47 -0
- data/examples/words/config/routes.rb +5 -0
- data/examples/words/config/secrets.yml +22 -0
- data/examples/words/config/spring.rb +6 -0
- data/examples/words/db/migrate/20160921223808_create_words.rb +9 -0
- data/examples/words/db/schema.rb +28 -0
- data/examples/words/log/.keep +0 -0
- data/examples/words/public/404.html +67 -0
- data/examples/words/public/422.html +67 -0
- data/examples/words/public/500.html +66 -0
- data/examples/words/public/apple-touch-icon-precomposed.png +0 -0
- data/examples/words/public/apple-touch-icon.png +0 -0
- data/examples/words/public/favicon.ico +0 -0
- data/examples/words/public/robots.txt +5 -0
- data/examples/words/tmp/.keep +0 -0
- data/examples/words/vendor/assets/javascripts/.keep +0 -0
- data/examples/words/vendor/assets/stylesheets/.keep +0 -0
- data/hyper-mesh.gemspec +82 -0
- data/lib/active_record_base.rb +152 -0
- data/lib/enumerable/pluck.rb +6 -0
- data/lib/hyper-mesh.rb +62 -0
- data/lib/hypermesh/version.rb +3 -0
- data/lib/opal/equality_patches.rb +15 -0
- data/lib/opal/parse_patch.rb +14 -0
- data/lib/opal/set_patches.rb +8 -0
- data/lib/reactive_record/active_record/aggregations.rb +69 -0
- data/lib/reactive_record/active_record/associations.rb +111 -0
- data/lib/reactive_record/active_record/base.rb +9 -0
- data/lib/reactive_record/active_record/class_methods.rb +177 -0
- data/lib/reactive_record/active_record/error.rb +26 -0
- data/lib/reactive_record/active_record/instance_methods.rb +129 -0
- data/lib/reactive_record/active_record/public_columns_hash.rb +19 -0
- data/lib/reactive_record/active_record/reactive_record/base.rb +520 -0
- data/lib/reactive_record/active_record/reactive_record/collection.rb +517 -0
- data/lib/reactive_record/active_record/reactive_record/column_types.rb +67 -0
- data/lib/reactive_record/active_record/reactive_record/dummy_value.rb +218 -0
- data/lib/reactive_record/active_record/reactive_record/isomorphic_base.rb +532 -0
- data/lib/reactive_record/active_record/reactive_record/reactive_set_relationship_helpers.rb +189 -0
- data/lib/reactive_record/active_record/reactive_record/scoped_collection.rb +62 -0
- data/lib/reactive_record/active_record/reactive_record/unscoped_collection.rb +16 -0
- data/lib/reactive_record/active_record/reactive_record/while_loading.rb +299 -0
- data/lib/reactive_record/engine.rb +13 -0
- data/lib/reactive_record/interval.rb +190 -0
- data/lib/reactive_record/permissions.rb +102 -0
- data/lib/reactive_record/pry.rb +13 -0
- data/lib/reactive_record/reactive_scope.rb +18 -0
- data/lib/reactive_record/scope_description.rb +108 -0
- data/lib/reactive_record/serializers.rb +7 -0
- data/lib/reactive_record/server_data_cache.rb +347 -0
- data/lib/reactive_record/version.rb +3 -0
- data/lib/sources/hyper-mesh/pusher.js +98 -0
- data/lib/synchromesh/action_cable.rb +39 -0
- data/lib/synchromesh/client_drivers.rb +357 -0
- data/lib/synchromesh/configuration.rb +40 -0
- data/lib/synchromesh/connection.rb +144 -0
- data/lib/synchromesh/policy.rb +504 -0
- data/lib/synchromesh/reactive_record/permission_patches.rb +43 -0
- data/lib/synchromesh/synchromesh.rb +155 -0
- data/lib/synchromesh/synchromesh_controller.rb +154 -0
- data/logo.jpg +0 -0
- data/path_release_steps.md +0 -0
- data/reactive_record_test_app/Gemfile +15 -0
- data/reactive_record_test_app/Gemfile.lock +209 -0
- data/reactive_record_test_app/README.rdoc +261 -0
- data/reactive_record_test_app/Rakefile +7 -0
- data/reactive_record_test_app/app/assets/javascripts/application.rb +5 -0
- data/reactive_record_test_app/app/assets/javascripts/components/another_component.rb +24 -0
- data/reactive_record_test_app/app/assets/javascripts/components/empty_component.rb +6 -0
- data/reactive_record_test_app/app/assets/javascripts/components/todo_item_component.js.rb +16 -0
- data/reactive_record_test_app/app/assets/javascripts/components/todos_component.js.rb +42 -0
- data/reactive_record_test_app/app/assets/javascripts/components/todos_main_component.rb +49 -0
- data/reactive_record_test_app/app/assets/javascripts/react_js_test_only.js +21618 -0
- data/reactive_record_test_app/app/assets/javascripts/reactive_record_config.js +2 -0
- data/reactive_record_test_app/app/assets/javascripts/spec/reactive_record_xspec.js.rb +42 -0
- data/reactive_record_test_app/app/assets/stylesheets/application.css +13 -0
- data/reactive_record_test_app/app/controllers/application_controller.rb +8 -0
- data/reactive_record_test_app/app/controllers/home_controller.rb +7 -0
- data/reactive_record_test_app/app/controllers/test_controller.rb +7 -0
- data/reactive_record_test_app/app/helpers/application_helper.rb +2 -0
- data/reactive_record_test_app/app/mailers/.gitkeep +0 -0
- data/reactive_record_test_app/app/models/.gitkeep +0 -0
- data/reactive_record_test_app/app/policies/application_policy.rb +5 -0
- data/reactive_record_test_app/app/views/components.rb +4 -0
- data/reactive_record_test_app/app/views/components/test.rb +18 -0
- data/reactive_record_test_app/app/views/home/index.html.erb +1 -0
- data/reactive_record_test_app/app/views/layouts/application.html.erb +17 -0
- data/reactive_record_test_app/app/views/models.rb +1 -0
- data/reactive_record_test_app/app/views/models/address.rb +13 -0
- data/reactive_record_test_app/app/views/models/comment.rb +19 -0
- data/reactive_record_test_app/app/views/models/todo_item.rb +36 -0
- data/reactive_record_test_app/app/views/models/user.rb +78 -0
- data/reactive_record_test_app/config.ru +33 -0
- data/reactive_record_test_app/config/application.rb +73 -0
- data/reactive_record_test_app/config/boot.rb +10 -0
- data/reactive_record_test_app/config/database.yml +25 -0
- data/reactive_record_test_app/config/environment.rb +5 -0
- data/reactive_record_test_app/config/environments/development.rb +43 -0
- data/reactive_record_test_app/config/environments/production.rb +70 -0
- data/reactive_record_test_app/config/environments/test.rb +41 -0
- data/reactive_record_test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/reactive_record_test_app/config/initializers/inflections.rb +15 -0
- data/reactive_record_test_app/config/initializers/mime_types.rb +5 -0
- data/reactive_record_test_app/config/initializers/secret_token.rb +7 -0
- data/reactive_record_test_app/config/initializers/session_store.rb +8 -0
- data/reactive_record_test_app/config/initializers/wrap_parameters.rb +14 -0
- data/reactive_record_test_app/config/locales/en.yml +5 -0
- data/reactive_record_test_app/config/routes.rb +7 -0
- data/reactive_record_test_app/db/migrate/20150617002932_create_todo_items.rb +11 -0
- data/reactive_record_test_app/db/migrate/20150617134028_create_users.rb +14 -0
- data/reactive_record_test_app/db/migrate/20150729195556_add_address_to_user.rb +20 -0
- data/reactive_record_test_app/db/migrate/20150826142045_create_comments.rb +10 -0
- data/reactive_record_test_app/db/migrate/20150828172008_add_single_comment_to_todo_item.rb +5 -0
- data/reactive_record_test_app/db/migrate/20150908184118_add_address_id_to_user.rb +5 -0
- data/reactive_record_test_app/db/migrate/20150917220236_add_second_address_to_user.rb +10 -0
- data/reactive_record_test_app/db/migrate/20151009000111_add_test_data_attributes_to_user.rb +6 -0
- data/reactive_record_test_app/db/migrate/20160129182544_add_test_enum_to_user.rb +5 -0
- data/reactive_record_test_app/db/schema.rb +63 -0
- data/reactive_record_test_app/db/seeds.rb +60 -0
- data/reactive_record_test_app/public/404.html +26 -0
- data/reactive_record_test_app/public/422.html +26 -0
- data/reactive_record_test_app/public/500.html +25 -0
- data/reactive_record_test_app/public/favicon.ico +0 -0
- data/reactive_record_test_app/script/rails +6 -0
- data/reactive_record_test_app/spec-opal/active-record/aggregations_spec.rb +41 -0
- data/reactive_record_test_app/spec-opal/active-record/associations_spec.rb +75 -0
- data/reactive_record_test_app/spec-opal/active-record/base_spec.rb +126 -0
- data/reactive_record_test_app/spec-opal/active-record/dummy_value_spec.rb +27 -0
- data/reactive_record_test_app/spec-opal/active-record/edge_cases_spec.rb +116 -0
- data/reactive_record_test_app/spec-opal/active-record/enum_spec.rb +43 -0
- data/reactive_record_test_app/spec-opal/active-record/instance_methods_spec.rb +53 -0
- data/reactive_record_test_app/spec-opal/active-record/non_ar_aggregations_spec.rb +74 -0
- data/reactive_record_test_app/spec-opal/active-record/permissions_spec.rb +170 -0
- data/reactive_record_test_app/spec-opal/active-record/prerendering_spec.rb +49 -0
- data/reactive_record_test_app/spec-opal/active-record/reactive_record_load_spec.rb +23 -0
- data/reactive_record_test_app/spec-opal/active-record/rendering_spec.rb +221 -0
- data/reactive_record_test_app/spec-opal/active-record/save_spec.rb +125 -0
- data/reactive_record_test_app/spec-opal/active-record/scope_spec.rb +85 -0
- data/reactive_record_test_app/spec-opal/active-record/update_aggregations_spec.rb +76 -0
- data/reactive_record_test_app/spec-opal/active-record/update_attributes_spec.rb +186 -0
- data/reactive_record_test_app/spec-opal/active-record/virtual_methods_spec.rb +71 -0
- data/reactive_record_test_app/spec-opal/index.html.erb +11 -0
- data/reactive_record_test_app/spec-opal/spec_helper.js.rb +268 -0
- data/reactive_record_test_app/spec-opal/vendor/es5-shim.min.js +6 -0
- data/reactive_record_test_app/spec_dont_run/README.md +26 -0
- data/reactive_record_test_app/spec_dont_run/moved_to_main_spec_dir/zzzmany_to_many_spec_moved_to_main_suite.rb +30 -0
- data/reactive_record_test_app/spec_dont_run/moved_to_main_spec_dir/zzzrevert_record_spec_moved.rb +78 -0
- data/reactive_record_test_app/spec_dont_run/moved_to_main_spec_dir/zzzupdate_associations_spec_moved.rb +142 -0
- data/reactive_record_test_app/spec_dont_run/moved_to_main_spec_dir/zzzupdate_scopes_movedspec.rb +48 -0
- data/remote.md +115 -0
- data/spec/bin/firebug-2.0.13-fx.xpi +0 -0
- data/spec/component_helpers_xspec.rb +49 -0
- data/spec/factories/child_model.rb +5 -0
- data/spec/factories/comment.rb +5 -0
- data/spec/factories/test_models.rb +5 -0
- data/spec/factories/todo.rb +5 -0
- data/spec/factories/user.rb +5 -0
- data/spec/reactive_record/edge_cases_spec.rb +31 -0
- data/spec/reactive_record/factory.rb +62 -0
- data/spec/reactive_record/many_to_many_spec.rb +50 -0
- data/spec/reactive_record/play.rb +64 -0
- data/spec/reactive_record/pry_rescue_xspec.rb +48 -0
- data/spec/reactive_record/revert_spec.rb +112 -0
- data/spec/reactive_record/update_associations_spec.rb +189 -0
- data/spec/reactive_record/update_scopes_spec.rb +53 -0
- data/spec/spec_helper.rb +366 -0
- data/spec/support/component_helpers.rb +351 -0
- data/spec/synchromesh/column_types/column_type_spec.rb +302 -0
- data/spec/synchromesh/connection_spec.rb +144 -0
- data/spec/synchromesh/crud_access_regulation/broadcast_controls_access_spec.rb +105 -0
- data/spec/synchromesh/crud_access_regulation/model_policies_spec.rb +131 -0
- data/spec/synchromesh/examples/dictionary.rb +239 -0
- data/spec/synchromesh/examples/dictionary_with_client_scopes.rb +196 -0
- data/spec/synchromesh/examples/random_examples.rb +100 -0
- data/spec/synchromesh/examples/scoped_todos_spec.rb +167 -0
- data/spec/synchromesh/integration/authorization_spec.rb +111 -0
- data/spec/synchromesh/integration/default_scope_spec.rb +121 -0
- data/spec/synchromesh/integration/has_many_through_spec.rb +173 -0
- data/spec/synchromesh/integration/relationships_spec.rb +263 -0
- data/spec/synchromesh/integration/scope_spec.rb +553 -0
- data/spec/synchromesh/integration/synchromesh_spec.rb +80 -0
- data/spec/synchromesh/integration/test_components.rb +18 -0
- data/spec/synchromesh/integration/transports_spec.rb +308 -0
- data/spec/synchromesh/policies/auto_connect_spec.rb +60 -0
- data/spec/synchromesh/policies/auto_loader_spec.rb +34 -0
- data/spec/synchromesh/policies/policy_methods_spec.rb +85 -0
- data/spec/synchromesh/policies/regulate_all_broadcasts_spec.rb +315 -0
- data/spec/synchromesh/policies/regulate_broadcast_spec.rb +370 -0
- data/spec/synchromesh/policies/regulate_class_connection_spec.rb +50 -0
- data/spec/synchromesh/policies/regulate_instance_connection_spec.rb +66 -0
- data/spec/test_app/Gemfile +61 -0
- data/spec/test_app/Gemfile.lock +253 -0
- data/spec/test_app/Rakefile +6 -0
- data/spec/test_app/app/assets/javascripts/application.js +6 -0
- data/spec/test_app/app/assets/stylesheets/application.css +15 -0
- data/spec/test_app/app/controllers/application_controller.rb +13 -0
- data/spec/test_app/app/controllers/test_controller.rb +5 -0
- data/spec/test_app/app/models/_react_public_models.rb +2 -0
- data/spec/test_app/app/models/public/address.rb +13 -0
- data/spec/test_app/app/models/public/child_model.rb +3 -0
- data/spec/test_app/app/models/public/comment.rb +25 -0
- data/spec/test_app/app/models/public/test_model.rb +5 -0
- data/spec/test_app/app/models/public/todo.rb +6 -0
- data/spec/test_app/app/models/public/todo_item.rb +36 -0
- data/spec/test_app/app/models/public/user.rb +88 -0
- data/spec/test_app/app/policies/auto_loader_test_classa_policy.rb +3 -0
- data/spec/test_app/app/policies/auto_loader_test_classb_policy.rb +3 -0
- data/spec/test_app/app/policies/auto_loader_test_classc_policy.rb +3 -0
- data/spec/test_app/app/policies/auto_loader_test_classd_policy.rb +3 -0
- data/spec/test_app/app/views/components.rb +14 -0
- data/spec/test_app/app/views/components/show.rb +5 -0
- data/spec/test_app/app/views/layouts/application.html.erb +14 -0
- data/spec/test_app/bin/bundle +3 -0
- data/spec/test_app/bin/rails +4 -0
- data/spec/test_app/bin/rake +4 -0
- data/spec/test_app/bin/setup +29 -0
- data/spec/test_app/config.ru +4 -0
- data/spec/test_app/config/application.rb +42 -0
- data/spec/test_app/config/boot.rb +6 -0
- data/spec/test_app/config/cable.yml +10 -0
- data/spec/test_app/config/database.yml +47 -0
- data/spec/test_app/config/environment.rb +5 -0
- data/spec/test_app/config/environments/development.rb +41 -0
- data/spec/test_app/config/environments/production.rb +79 -0
- data/spec/test_app/config/environments/test.rb +42 -0
- data/spec/test_app/config/initializers/assets.rb +11 -0
- data/spec/test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/test_app/config/initializers/cookies_serializer.rb +3 -0
- data/spec/test_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/test_app/config/initializers/inflections.rb +16 -0
- data/spec/test_app/config/initializers/mime_types.rb +4 -0
- data/spec/test_app/config/initializers/session_store.rb +3 -0
- data/spec/test_app/config/initializers/synchromesh.rb +11 -0
- data/spec/test_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/test_app/config/locales/en.yml +23 -0
- data/spec/test_app/config/routes.rb +61 -0
- data/spec/test_app/config/secrets.yml +22 -0
- data/spec/test_app/db/development.sqlite3 +0 -0
- data/spec/test_app/db/migrate/20160731182106_create_test_models.rb +75 -0
- data/spec/test_app/db/schema.rb +88 -0
- data/spec/test_app/db/seeds.rb +7 -0
- data/spec/test_app/lib/assets/.keep +0 -0
- data/spec/test_app/log/.keep +0 -0
- data/spec/test_app/public/404.html +67 -0
- data/spec/test_app/public/422.html +67 -0
- data/spec/test_app/public/500.html +66 -0
- data/spec/test_app/public/favicon.ico +0 -0
- data/spec/vendor/es5-shim.min.js +6 -0
- data/terminal.md +66 -0
- metadata +1175 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
## ActiveRecord Scope Enhancement
|
2
|
+
|
3
|
+
When the client receives notification that a record has changed HyperMesh finds the set of currently rendered scopes that might be effected, and requests them to be updated from the server.
|
4
|
+
|
5
|
+
On the server scopes are a useful way to structure code. **On the client** scopes are vital as they limit the amount of data loaded, viewed, and updated on the client. Consider a factory floor management system that shows *job* state as work flows through the factory. There may be millions of jobs that a production floor browser is authorized to view, but at any time there are probably only 50 being shown. Using ActiveRecord scopes is the way synchromesh keeps the data requested by the browser limited to a reasonable amount.
|
6
|
+
|
7
|
+
To make scopes work efficiently on the client HyperMesh adds some features to the ActiveRecord `scope` and `default_scope` macros. Note you must use the `scope` macro (and not class methods) for things to work with HyperMesh.
|
8
|
+
|
9
|
+
The additional features are accessed via the `:joins`, `:client`, and `:select` options.
|
10
|
+
|
11
|
+
The `:joins` option tells the synchromesh client which models are joined with the scope. *You must add a `:joins` option if the scope has any data base join operations in it, otherwise if a joined model changes, synchromesh will not know to update the scope.*
|
12
|
+
|
13
|
+
The `:client` option provides the client a way to update scopes without having to contact the server. Unlike the `:joins` option this is an optimization and is not required for scopes to work.
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
class Todo < ActiveRecord::Base
|
17
|
+
|
18
|
+
# Standard ActiveRecord form:
|
19
|
+
# the proc will be evaluated as normal on the server, and as needed updates
|
20
|
+
# will be requested from the clients
|
21
|
+
|
22
|
+
scope :active, -> () { where(completed: true) }
|
23
|
+
|
24
|
+
# In the simple form the scope will be reevaluated if the model that is
|
25
|
+
# being scoped changes, and if the scope is currently being used to render data.
|
26
|
+
|
27
|
+
# If the scope joins with other data you will need to specify this by
|
28
|
+
# passing a relationship or array of relationships to the `joins` option.
|
29
|
+
|
30
|
+
scope :with_recent_comments,
|
31
|
+
-> { joins(:comments).where('comment.created_at >= ?', Time.now-1.week) },
|
32
|
+
joins: ['comments'] # or joins: 'comments'
|
33
|
+
|
34
|
+
# Now with_recent_comments will be re-evaluated whenever a Todo record, or a Comment
|
35
|
+
# joined with a Todo change.
|
36
|
+
|
37
|
+
# Normally whenever synchromesh detects that a scope may be effected by a changed
|
38
|
+
# model, it will request the scope be re-evaluated on the server. To offload this
|
39
|
+
# computation to the client provide a client side scope method:
|
40
|
+
|
41
|
+
scope :with_recent_comments,
|
42
|
+
-> { joins(:comments).where('comment.created_at >= ?', Time.now-1.week) },
|
43
|
+
joins: ['comments']
|
44
|
+
client: -> { comments.detect { |comment| comment.created_at >= Time.now-1.week }
|
45
|
+
|
46
|
+
# The client proc is executed on each candidate record, and if it returns true the record
|
47
|
+
# will be added to the scope.
|
48
|
+
|
49
|
+
# Instead of a client proc you can provide a select proc, which will receive the entire,
|
50
|
+
# collection which can then be filtered and sorted.
|
51
|
+
|
52
|
+
scope :sort_by_created_at,
|
53
|
+
-> { order('created_at DESC') }
|
54
|
+
select: -> { sort { |a, b| b.created_at <=> a.created_at }}
|
55
|
+
|
56
|
+
# To keep things tidy you can specify the server scope proc with the :server option
|
57
|
+
|
58
|
+
scope :completed,
|
59
|
+
server: -> { where(complete: true) }
|
60
|
+
client: -> { complete }
|
61
|
+
|
62
|
+
# The expressions in the joins array can be arbitrary sequences of relationships and
|
63
|
+
# scopes such as 'comments.author'.
|
64
|
+
|
65
|
+
scope :with_managers_comments,
|
66
|
+
server: -> { ... }
|
67
|
+
joins: ['comments.author', 'owner']
|
68
|
+
client: -> { comments.detect { |comment| comment.author == owner.manager }}}
|
69
|
+
|
70
|
+
# You can also use the client, select, server, and joins option with the default_scope macro
|
71
|
+
|
72
|
+
default_scope server: -> { where(deleted: false).order('updated_at DESC') }
|
73
|
+
select: -> { select { |r| !r.deleted }.sort { |a, b| b <=> a } }
|
74
|
+
|
75
|
+
# NOTE: it is highly recommend to provide a client proc with default_scopes. Otherwise
|
76
|
+
# every change is going to require a server interaction regardless of what other client procs
|
77
|
+
# you provide.
|
78
|
+
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
#### How it works
|
83
|
+
|
84
|
+
Consider this scope on the Todo model
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
scope :with_managers_comments,
|
88
|
+
server: -> { joins(owner: :manager, comments: :author).where('managers_users.id = authors_comments.id').distinct },
|
89
|
+
client: -> { comments.detect { |comment| comment.author == owner.manager }}
|
90
|
+
joins: ['comments.author', 'owner']
|
91
|
+
```
|
92
|
+
|
93
|
+
The joins 'comments.author' relationship is inverted so that we have User 'has_many' Comments which 'belongs_to' Todos.
|
94
|
+
|
95
|
+
Thus we now know that whenever a User or a Comment changes this may effect our with_managers_comments scope
|
96
|
+
|
97
|
+
Likewise 'owner' becomes User 'has_many' Todos.
|
98
|
+
|
99
|
+
Lets say that a user changes teams and now has a new manager. This means according to the relationships that the
|
100
|
+
User model will change (i.e. there will be a new manager_id in the User model) and thus all Todos belonging to that
|
101
|
+
User are subject to evaluation.
|
102
|
+
|
103
|
+
While the server side proc efficiently delivers all the objects in the scope, the client side proc just needs to incrementally update the scope.
|
File without changes
|
@@ -0,0 +1,121 @@
|
|
1
|
+
### Simple Poller Quickstart
|
2
|
+
|
3
|
+
The easiest way to get started is to use the built-in simple polling transport.
|
4
|
+
|
5
|
+
#### 1 Get yourself a rails app
|
6
|
+
|
7
|
+
Either take an existing rails app, or create a new one the usual way.
|
8
|
+
|
9
|
+
#### 2 Add ReactRb
|
10
|
+
|
11
|
+
If you have not already installed the `hyper-react` and `reactive-record` gems, then do so now using the [reactrb-rails-generator](https://github.com/hyper-react/reactrb-rails-generator) gem.
|
12
|
+
|
13
|
+
- add `gem 'reactrb-rails-generator'` to your gem file (in the development section)
|
14
|
+
- run `bundle install`
|
15
|
+
- run `bundle exec rails g hyper-react:install --all` (make sure to use the --all option)
|
16
|
+
- run `bundle update`
|
17
|
+
|
18
|
+
#### 3 Add the synchromesh gem
|
19
|
+
|
20
|
+
- add `gem 'synchromesh', git: 'https://github.com/hyper-react/synchromesh', branch: 'authorization-policies'`
|
21
|
+
- then `bundle install`
|
22
|
+
- and in `app/views/components.rb` add `require 'hyper-mesh'`
|
23
|
+
immediately below`require 'reactive-record'`
|
24
|
+
|
25
|
+
#### 4 Set the transport
|
26
|
+
|
27
|
+
Once you have hyper-react installed then add this initializer:
|
28
|
+
```ruby
|
29
|
+
#config/initializers/synchromesh.rb
|
30
|
+
HyperMesh.configuration do |config|
|
31
|
+
config.transport = :simple_poller
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
#### 5 Make sure caching is enabled
|
36
|
+
|
37
|
+
HyperMesh uses the rails cache to keep track of what connections are alive in a transport independent fashion. Rails 5 by default will have caching off in development mode.
|
38
|
+
|
39
|
+
Check in `config/development.rb` and make sure that `cache_store` is never being set to `:null_store`.
|
40
|
+
|
41
|
+
If you would like to be able to interact via
|
42
|
+
the `rails console` you should set the store to be something like this:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
# config/development.rb
|
46
|
+
Rails.application.configure do
|
47
|
+
config.cache_store = :file_store, './rails_cache_dir'
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
#### 6 Define Your Policies
|
52
|
+
|
53
|
+
To start just open everything up by adding a policies directory and defining a policy file like this:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
# app/policies/application_policy.rb
|
57
|
+
class ApplicationPolicy
|
58
|
+
always_allow_connection
|
59
|
+
regulate_all_broadcasts { |policy| policy.send_all }
|
60
|
+
allow_change(to: :all, on: [:create, :update, :destroy]) { true }
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
#### 8 Try It Out
|
65
|
+
|
66
|
+
If you don't already have a model to play with, add one now:
|
67
|
+
|
68
|
+
`bundle exec rails generate model Word text:string`
|
69
|
+
|
70
|
+
`bundle exec rake db:migrate`
|
71
|
+
|
72
|
+
Whatever model(s) you will plan to access on the client need to moved to the `app/models/public` directory. This allows reactive-record to build a client side proxy for the models. Models not moved will be completely invisible on the client side.
|
73
|
+
|
74
|
+
If you don't already have a simple component to play with, here is a simple one (make sure you add the Word model):
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
# app/views/components/app.rb
|
78
|
+
class App < React::Component::Base
|
79
|
+
|
80
|
+
def add_new_word
|
81
|
+
# for fun we will use setgetgo.com to get random words!
|
82
|
+
HTTP.get("http://randomword.setgetgo.com/get.php", dataType: :jsonp) do |response|
|
83
|
+
Word.new(text: response.json[:Word]).save
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
render(DIV) do
|
88
|
+
SPAN { "Count of Words: #{Word.count}" }
|
89
|
+
BUTTON { "add another" }.on(:click) { add_new_word }
|
90
|
+
UL do
|
91
|
+
Word.each { |word| LI { word.text } }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
Add a controller:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
#app/controllers/test_controller.rb
|
101
|
+
class TestController < ApplicationController
|
102
|
+
def app
|
103
|
+
render_component
|
104
|
+
end
|
105
|
+
end
|
106
|
+
```
|
107
|
+
|
108
|
+
Add the `test` route to your routes file:
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
#app/config/routes.rb
|
112
|
+
|
113
|
+
get 'test', to: 'test#app'
|
114
|
+
|
115
|
+
```
|
116
|
+
|
117
|
+
Fire up rails with `bundle exec rails s` and open your app in a couple of browsers. As data changes you should see them all updating together.
|
118
|
+
|
119
|
+
You can also fire up a rails console, and then for example do a `Word.new(text: "Hello").save` and again see any browsers updating.
|
120
|
+
|
121
|
+
If you want to go into more details with example check out [words-example](/docs/words-example.md)
|
@@ -0,0 +1,116 @@
|
|
1
|
+
Lets look at part of a very simple Todo application with one model:
|
2
|
+
|
3
|
+
```ruby
|
4
|
+
# app/models/public/todo.rb <- public models are accessible on the client
|
5
|
+
class Todo < ActiveRecord::Base
|
6
|
+
scope :active ->() { where(completed: true) }
|
7
|
+
scope :complete ->() { where(completed: false) }
|
8
|
+
end
|
9
|
+
```
|
10
|
+
|
11
|
+
To show our Todo's we might have a very simple app like this:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
# app/views/components/app.rb
|
15
|
+
class App < React::Component::Base
|
16
|
+
|
17
|
+
define_state scope: :active
|
18
|
+
define_state new_todo: Todo.new
|
19
|
+
|
20
|
+
def todos # display our list of todos
|
21
|
+
ul do
|
22
|
+
Todo.send(state.scope).each do |todo|
|
23
|
+
li do
|
24
|
+
status(todo); todo.title.span; delete_button(todo)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def status(todo) # display / change the status
|
31
|
+
checkbox(type: :checkbox, checked: todo.completed)
|
32
|
+
.on(:click) do
|
33
|
+
todo.completed = !todo.completed
|
34
|
+
todo.save
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def delete_button(todo) # delete a todo
|
39
|
+
button { "delete!" }.on(:click) { todo.destroy }
|
40
|
+
end
|
41
|
+
|
42
|
+
def save_new_todo # save a new todo
|
43
|
+
state.new_todo.save
|
44
|
+
state.new_todo! Todo.new
|
45
|
+
end
|
46
|
+
|
47
|
+
def link(to) # display a link to a scope
|
48
|
+
button { to }.on(:click) { state.scope! to }
|
49
|
+
end
|
50
|
+
|
51
|
+
render do # render everything
|
52
|
+
div do
|
53
|
+
todos
|
54
|
+
input(value: state.new_todo.title)
|
55
|
+
.on(:change) { |e| state.new_todo.title = e.target.value }
|
56
|
+
.on(:key_down) { |e| save_new_todo if e.key_code == 13 }
|
57
|
+
div { link(:all); link(:active); link(:complete) }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
Finally we will need a controller:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
class HomeController < ApplicationController
|
67
|
+
def app
|
68
|
+
render_component
|
69
|
+
end
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
Except for configuration that is our complete App. When the page loads it will show all the todos currently in the database. As the user changes the state of the Todos (or adds more) the changes will be persisted via the Todo model.
|
74
|
+
|
75
|
+
In order to have the changes on one browser be synchronized across all browsers we have to set up some *policies* to define the desired behavior. Here is a very simple policy without any protection:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
#app/policies/application_policy.rb
|
79
|
+
class ApplicationPolicy
|
80
|
+
always_allow_connection # any browser may connect
|
81
|
+
regulate_all_broadcasts &:send_all # send all changes from all models
|
82
|
+
allow_change(to: :all, on: [:create, :update, :destroy])
|
83
|
+
end
|
84
|
+
```
|
85
|
+
|
86
|
+
That is it!
|
87
|
+
|
88
|
+
Lets walk through what happens users interact with the system.
|
89
|
+
|
90
|
+
When the page first renders (on the server) our `App` component executes (on the server) and renders the initial view. This is no different from the normal rendering cycle of any rails view, the only difference is we are using `Ruby` as our templating language.
|
91
|
+
|
92
|
+
Compare the lines:
|
93
|
+
```ruby
|
94
|
+
ul do
|
95
|
+
Todo.send(state.scope).each do |todo|
|
96
|
+
li do
|
97
|
+
status(todo); todo.title.span; delete_button(todo)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
```
|
102
|
+
to the equivilent html.erb file:
|
103
|
+
```html
|
104
|
+
<ul>
|
105
|
+
<% Todo.send(@scope).each do |todo| %>
|
106
|
+
<li>
|
107
|
+
...
|
108
|
+
</li>
|
109
|
+
<% end %>
|
110
|
+
</ul>
|
111
|
+
```
|
112
|
+
The only difference is your brain doesn't hurt from all the syntactic context switching.
|
113
|
+
|
114
|
+
So the server builds a pile of html and dumps it the browser as normal, but once on the browser we have the exact same ruby code running their as well. It will automatically add all of event handlers (`on(:click), on(:change)`, etc), and as the events occur the underlying react.js system will cause portions of our code to rerender.
|
115
|
+
|
116
|
+
Also during the client load any connections allowed to the browser will be established so that changes in the server database made by other sources will get broadcast to us.
|
@@ -0,0 +1,65 @@
|
|
1
|
+
## Random Words example
|
2
|
+
|
3
|
+
This is the example app used by the quick start guides, and if you want to dive deeper this is the place to be.
|
4
|
+
|
5
|
+
If you have not already done so, follow any one of the quick start guides to set up the basic system. Make sure to follow the steps in the last section and add a `Word` model, a `App` component, and a controller and route.
|
6
|
+
|
7
|
+
### The initial component:
|
8
|
+
|
9
|
+
Your initial component should look like this:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
# app/views/components/app.rb
|
13
|
+
class App < React::Component::Base
|
14
|
+
|
15
|
+
def add_new_word
|
16
|
+
# for fun we will use setgetgo.com to get random words!
|
17
|
+
HTTP.get("http://randomword.setgetgo.com/get.php", dataType: :jsonp) do |response|
|
18
|
+
Word.new(text: response.json[:Word]).save
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
render(DIV) do
|
23
|
+
SPAN { "Count of Words: #{Word.count}" }
|
24
|
+
BUTTON { "add another" }.on(:click) { add_new_word }
|
25
|
+
UL do
|
26
|
+
Word.each { |word| LI { word.text } }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
```
|
31
|
+
|
32
|
+
Before going further lets understand exactly what is going on here.
|
33
|
+
|
34
|
+
1) Our controller has a method named `app`, so by convention Reactrb will look for a
|
35
|
+
component class named `App`, which it finds and *mounts* where ever the the *layout* yields to the view.
|
36
|
+
|
37
|
+
Take a second to look at your `application.html.erb` and find the `<%= yield %>`. That is the normal rails way of
|
38
|
+
indicating where the view requested by the controller (in the case our component) should be rendered.
|
39
|
+
|
40
|
+
2) The component is rendered on the server like any other view. The `render` callback defines exactly what to render.
|
41
|
+
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
# app/views/components/app.rb
|
45
|
+
class App < React::Component::Base
|
46
|
+
|
47
|
+
def add_new_word
|
48
|
+
# for fun we will use setgetgo.com to get random words!
|
49
|
+
word = Word.new(text: '')
|
50
|
+
Word << word # force our local list to update before the save
|
51
|
+
HTTP.get("http://randomword.setgetgo.com/get.php", dataType: :jsonp) do |response|
|
52
|
+
word.text = response.json[:Word]
|
53
|
+
word.save
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
render(DIV) do
|
58
|
+
SPAN { "Count of Words: #{Word.count}" }
|
59
|
+
BUTTON { "add another" }.on(:click) { add_new_word }
|
60
|
+
UL do
|
61
|
+
Word.sort.each { |word| LI { word.text.empty? ? 'loading...' : word.text } }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
```
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
2
|
+
#
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
5
|
+
# git config --global core.excludesfile '~/.gitignore_global'
|
6
|
+
|
7
|
+
# Ignore bundler config.
|
8
|
+
/.bundle
|
9
|
+
|
10
|
+
# Ignore the default SQLite database.
|
11
|
+
/db/*.sqlite3
|
12
|
+
/db/*.sqlite3-journal
|
13
|
+
|
14
|
+
# Ignore all logfiles and tempfiles.
|
15
|
+
/log/*
|
16
|
+
/tmp/*
|
17
|
+
!/log/.keep
|
18
|
+
!/tmp/.keep
|
19
|
+
|
20
|
+
# Ignore Byebug command history file.
|
21
|
+
.byebug_history
|
@@ -0,0 +1,58 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
|
4
|
+
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
|
5
|
+
gem 'rails', '~> 5.0.0', '>= 5.0.0.1'
|
6
|
+
# Use sqlite3 as the database for Active Record
|
7
|
+
gem 'sqlite3'
|
8
|
+
# Use Puma as the app server
|
9
|
+
gem 'puma', '~> 3.0'
|
10
|
+
# Use SCSS for stylesheets
|
11
|
+
gem 'sass-rails', '~> 5.0'
|
12
|
+
# Use Uglifier as compressor for JavaScript assets
|
13
|
+
gem 'uglifier', '>= 1.3.0'
|
14
|
+
# Use CoffeeScript for .coffee assets and views
|
15
|
+
gem 'coffee-rails', '~> 4.2'
|
16
|
+
# See https://github.com/rails/execjs#readme for more supported runtimes
|
17
|
+
# gem 'therubyracer', platforms: :ruby
|
18
|
+
|
19
|
+
# Use jquery as the JavaScript library
|
20
|
+
gem 'jquery-rails'
|
21
|
+
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
|
22
|
+
gem 'turbolinks', '~> 5'
|
23
|
+
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
|
24
|
+
gem 'jbuilder', '~> 2.5'
|
25
|
+
# Use Redis adapter to run Action Cable in production
|
26
|
+
# gem 'redis', '~> 3.0'
|
27
|
+
# Use ActiveModel has_secure_password
|
28
|
+
# gem 'bcrypt', '~> 3.1.7'
|
29
|
+
|
30
|
+
# Use Capistrano for deployment
|
31
|
+
# gem 'capistrano-rails', group: :development
|
32
|
+
|
33
|
+
group :development, :test do
|
34
|
+
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
|
35
|
+
gem 'byebug', platform: :mri
|
36
|
+
gem 'reactrb-rails-generator'
|
37
|
+
end
|
38
|
+
|
39
|
+
group :development do
|
40
|
+
# Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
|
41
|
+
gem 'web-console'
|
42
|
+
gem 'listen', '~> 3.0.5'
|
43
|
+
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
|
44
|
+
gem 'spring'
|
45
|
+
gem 'spring-watcher-listen', '~> 2.0.0'
|
46
|
+
end
|
47
|
+
|
48
|
+
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
|
49
|
+
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
|
50
|
+
|
51
|
+
gem 'hyper-react'
|
52
|
+
gem 'react-rails', '>= 1.3.0'
|
53
|
+
gem 'opal-rails', '>= 0.8.1'
|
54
|
+
gem 'therubyracer', platforms: :ruby
|
55
|
+
gem 'react-router-rails', '~> 0.13.3'
|
56
|
+
gem 'reactrb-router'
|
57
|
+
gem 'reactive-record', '>= 0.8.0'
|
58
|
+
gem 'synchromesh', path: '../..'
|