From 659da24af38b7d72aa983c7abd0ce3ff6aabfa51 Mon Sep 17 00:00:00 2001 From: Benjamin ter Kuile Date: Thu, 21 Dec 2017 11:36:52 +0100 Subject: [PATCH] initial copy commit --- .gitignore | 7 + .rspec | 1 + Gemfile | 32 ++ Gemfile.lock | 332 ++++++++++++++++++ LICENSE | 1 + README.md | 44 +++ Rakefile | 26 ++ app/assets/config/dunlop_ember_manifest.js | 2 + app/assets/images/dunlop/ember/.keep | 0 .../javascripts/dunlop/ember/application.js | 13 + .../stylesheets/dunlop/ember/application.css | 15 + .../dunlop/ember/application_controller.rb | 54 +++ .../dunlop/ember/sessions_controller.rb | 27 ++ .../dunlop/ember/users_controller.rb | 16 + .../dunlop/ember/application_helper.rb | 6 + app/jobs/dunlop/ember/application_job.rb | 6 + .../dunlop/ember/application_mailer.rb | 8 + app/services/flat_keys.rb | 51 +++ .../ember/application/ember_path.html.slim | 4 + .../layouts/dunlop/ember/application.html.erb | 14 + bin/rails | 13 + .../active_model_serializers_config.rb | 7 + config/routes.rb | 8 + config/spring.rb | 1 + dunlop-ember.gemspec | 29 ++ lib/dunlop/ember.rb | 9 + lib/dunlop/ember/api_base_controller.rb | 252 +++++++++++++ lib/dunlop/ember/cancan_safeguard.rb | 22 ++ lib/dunlop/ember/engine.rb | 14 + lib/dunlop/ember/version.rb | 5 + lib/generators/dunlop/ember/install/USAGE | 8 + .../dunlop/ember/install/install_generator.rb | 10 + .../active_model_serializers_config.rb | 5 + .../initializers/jsonapi_mime_type.rb | 8 + lib/tasks/dunlop/ember_tasks.rake | 4 + .../api/posts_controller/index_spec.rb | 110 ++++++ .../api/posts_controller/update_spec.rb | 42 +++ spec/dummy/Rakefile | 6 + spec/dummy/app/assets/config/manifest.js | 5 + spec/dummy/app/assets/images/.keep | 0 .../app/assets/javascripts/application.js | 13 + spec/dummy/app/assets/javascripts/cable.js | 13 + .../app/assets/javascripts/channels/.keep | 0 .../app/assets/javascripts/comments.coffee | 3 + .../app/assets/stylesheets/application.css | 15 + .../app/channels/application_cable/channel.rb | 4 + .../channels/application_cable/connection.rb | 4 + .../app/controllers/api/base_controller.rb | 5 + .../app/controllers/api/posts_controller.rb | 7 + .../app/controllers/application_controller.rb | 32 ++ .../app/controllers/comments_controller.rb | 58 +++ spec/dummy/app/controllers/concerns/.keep | 0 .../dummy/app/controllers/posts_controller.rb | 58 +++ spec/dummy/app/helpers/application_helper.rb | 2 + spec/dummy/app/helpers/comments_helper.rb | 2 + spec/dummy/app/helpers/posts_helper.rb | 2 + spec/dummy/app/jobs/application_job.rb | 2 + spec/dummy/app/mailers/application_mailer.rb | 4 + spec/dummy/app/models/ability.rb | 7 + spec/dummy/app/models/application_record.rb | 18 + spec/dummy/app/models/comment.rb | 3 + spec/dummy/app/models/concerns/.keep | 0 spec/dummy/app/models/execution_batch.rb | 3 + spec/dummy/app/models/post.rb | 3 + spec/dummy/app/models/user.rb | 11 + .../app/serializers/api/comment_serializer.rb | 4 + .../app/serializers/api/post_serializer.rb | 5 + spec/dummy/app/views/comments/_form.html.slim | 18 + spec/dummy/app/views/comments/edit.html.slim | 8 + spec/dummy/app/views/comments/index.html.slim | 25 ++ spec/dummy/app/views/comments/new.html.slim | 5 + spec/dummy/app/views/comments/show.html.slim | 15 + .../app/views/layouts/_messages.html.slim | 5 + .../app/views/layouts/_navigation.html.slim | 5 + .../views/layouts/_navigation_links.html.slim | 39 ++ .../app/views/layouts/application.html.slim | 27 ++ spec/dummy/app/views/layouts/mailer.html.erb | 13 + spec/dummy/app/views/layouts/mailer.text.erb | 1 + spec/dummy/app/views/posts/_form.html.slim | 15 + spec/dummy/app/views/posts/edit.html.slim | 8 + spec/dummy/app/views/posts/index.html.slim | 23 ++ spec/dummy/app/views/posts/new.html.slim | 5 + spec/dummy/app/views/posts/show.html.slim | 12 + spec/dummy/bin/bundle | 3 + spec/dummy/bin/rails | 4 + spec/dummy/bin/rake | 4 + spec/dummy/bin/setup | 34 ++ spec/dummy/bin/update | 29 ++ spec/dummy/config.ru | 5 + spec/dummy/config/application.rb | 37 ++ spec/dummy/config/boot.rb | 5 + spec/dummy/config/cable.yml | 9 + spec/dummy/config/database.yml | 25 ++ spec/dummy/config/environment.rb | 5 + spec/dummy/config/environments/development.rb | 58 +++ spec/dummy/config/environments/production.rb | 86 +++++ spec/dummy/config/environments/test.rb | 46 +++ .../application_controller_renderer.rb | 6 + spec/dummy/config/initializers/assets.rb | 11 + .../initializers/backtrace_silencers.rb | 7 + .../config/initializers/cookies_serializer.rb | 5 + spec/dummy/config/initializers/devise.rb | 277 +++++++++++++++ .../initializers/filter_parameter_logging.rb | 4 + spec/dummy/config/initializers/inflections.rb | 16 + spec/dummy/config/initializers/mime_types.rb | 4 + .../initializers/new_framework_defaults.rb | 24 ++ .../config/initializers/session_store.rb | 3 + .../config/initializers/wrap_parameters.rb | 14 + spec/dummy/config/locales/devise.en.yml | 64 ++++ spec/dummy/config/locales/en.yml | 23 ++ spec/dummy/config/puma.rb | 47 +++ spec/dummy/config/routes.rb | 11 + spec/dummy/config/secrets.yml | 22 ++ spec/dummy/config/spring.rb | 6 + .../db/migrate/20170926045124_create_posts.rb | 10 + .../migrate/20170926045157_create_comments.rb | 11 + .../20170926045305_devise_create_users.rb | 42 +++ ...50413_add_admin_and_role_names_to_users.rb | 9 + spec/dummy/db/schema.rb | 51 +++ spec/dummy/lib/assets/.keep | 0 spec/dummy/log/.keep | 0 spec/dummy/public/404.html | 67 ++++ spec/dummy/public/422.html | 67 ++++ spec/dummy/public/500.html | 66 ++++ .../public/apple-touch-icon-precomposed.png | 0 spec/dummy/public/apple-touch-icon.png | 0 spec/dummy/public/favicon.ico | 0 spec/factories/comments.rb | 7 + spec/factories/posts.rb | 6 + spec/factories/users.rb | 9 + .../dunlop/ember/api_base_controller_spec.rb | 62 ++++ spec/rails_helper.rb | 97 +++++ spec/routing/app_routing_spec.rb | 17 + spec/services/flat_keys_spec.rb | 58 +++ spec/spec_helper.rb | 96 +++++ 135 files changed, 3288 insertions(+) create mode 100644 .gitignore create mode 100644 .rspec create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 LICENSE create mode 100644 README.md create mode 100644 Rakefile create mode 100644 app/assets/config/dunlop_ember_manifest.js create mode 100644 app/assets/images/dunlop/ember/.keep create mode 100644 app/assets/javascripts/dunlop/ember/application.js create mode 100644 app/assets/stylesheets/dunlop/ember/application.css create mode 100644 app/controllers/dunlop/ember/application_controller.rb create mode 100644 app/controllers/dunlop/ember/sessions_controller.rb create mode 100644 app/controllers/dunlop/ember/users_controller.rb create mode 100644 app/helpers/dunlop/ember/application_helper.rb create mode 100644 app/jobs/dunlop/ember/application_job.rb create mode 100644 app/mailers/dunlop/ember/application_mailer.rb create mode 100644 app/services/flat_keys.rb create mode 100644 app/views/dunlop/ember/application/ember_path.html.slim create mode 100644 app/views/layouts/dunlop/ember/application.html.erb create mode 100755 bin/rails create mode 100644 config/initializers/active_model_serializers_config.rb create mode 100644 config/routes.rb create mode 100644 config/spring.rb create mode 100644 dunlop-ember.gemspec create mode 100644 lib/dunlop/ember.rb create mode 100644 lib/dunlop/ember/api_base_controller.rb create mode 100644 lib/dunlop/ember/cancan_safeguard.rb create mode 100644 lib/dunlop/ember/engine.rb create mode 100644 lib/dunlop/ember/version.rb create mode 100644 lib/generators/dunlop/ember/install/USAGE create mode 100644 lib/generators/dunlop/ember/install/install_generator.rb create mode 100644 lib/generators/dunlop/ember/install/templates/initializers/active_model_serializers_config.rb create mode 100644 lib/generators/dunlop/ember/install/templates/initializers/jsonapi_mime_type.rb create mode 100644 lib/tasks/dunlop/ember_tasks.rake create mode 100644 spec/controllers/api/posts_controller/index_spec.rb create mode 100644 spec/controllers/api/posts_controller/update_spec.rb create mode 100644 spec/dummy/Rakefile create mode 100644 spec/dummy/app/assets/config/manifest.js create mode 100644 spec/dummy/app/assets/images/.keep create mode 100644 spec/dummy/app/assets/javascripts/application.js create mode 100644 spec/dummy/app/assets/javascripts/cable.js create mode 100644 spec/dummy/app/assets/javascripts/channels/.keep create mode 100644 spec/dummy/app/assets/javascripts/comments.coffee create mode 100644 spec/dummy/app/assets/stylesheets/application.css create mode 100644 spec/dummy/app/channels/application_cable/channel.rb create mode 100644 spec/dummy/app/channels/application_cable/connection.rb create mode 100644 spec/dummy/app/controllers/api/base_controller.rb create mode 100644 spec/dummy/app/controllers/api/posts_controller.rb create mode 100644 spec/dummy/app/controllers/application_controller.rb create mode 100644 spec/dummy/app/controllers/comments_controller.rb create mode 100644 spec/dummy/app/controllers/concerns/.keep create mode 100644 spec/dummy/app/controllers/posts_controller.rb create mode 100644 spec/dummy/app/helpers/application_helper.rb create mode 100644 spec/dummy/app/helpers/comments_helper.rb create mode 100644 spec/dummy/app/helpers/posts_helper.rb create mode 100644 spec/dummy/app/jobs/application_job.rb create mode 100644 spec/dummy/app/mailers/application_mailer.rb create mode 100644 spec/dummy/app/models/ability.rb create mode 100644 spec/dummy/app/models/application_record.rb create mode 100644 spec/dummy/app/models/comment.rb create mode 100644 spec/dummy/app/models/concerns/.keep create mode 100644 spec/dummy/app/models/execution_batch.rb create mode 100644 spec/dummy/app/models/post.rb create mode 100644 spec/dummy/app/models/user.rb create mode 100644 spec/dummy/app/serializers/api/comment_serializer.rb create mode 100644 spec/dummy/app/serializers/api/post_serializer.rb create mode 100644 spec/dummy/app/views/comments/_form.html.slim create mode 100644 spec/dummy/app/views/comments/edit.html.slim create mode 100644 spec/dummy/app/views/comments/index.html.slim create mode 100644 spec/dummy/app/views/comments/new.html.slim create mode 100644 spec/dummy/app/views/comments/show.html.slim create mode 100644 spec/dummy/app/views/layouts/_messages.html.slim create mode 100644 spec/dummy/app/views/layouts/_navigation.html.slim create mode 100644 spec/dummy/app/views/layouts/_navigation_links.html.slim create mode 100644 spec/dummy/app/views/layouts/application.html.slim create mode 100644 spec/dummy/app/views/layouts/mailer.html.erb create mode 100644 spec/dummy/app/views/layouts/mailer.text.erb create mode 100644 spec/dummy/app/views/posts/_form.html.slim create mode 100644 spec/dummy/app/views/posts/edit.html.slim create mode 100644 spec/dummy/app/views/posts/index.html.slim create mode 100644 spec/dummy/app/views/posts/new.html.slim create mode 100644 spec/dummy/app/views/posts/show.html.slim create mode 100755 spec/dummy/bin/bundle create mode 100755 spec/dummy/bin/rails create mode 100755 spec/dummy/bin/rake create mode 100755 spec/dummy/bin/setup create mode 100755 spec/dummy/bin/update create mode 100644 spec/dummy/config.ru create mode 100644 spec/dummy/config/application.rb create mode 100644 spec/dummy/config/boot.rb create mode 100644 spec/dummy/config/cable.yml create mode 100644 spec/dummy/config/database.yml create mode 100644 spec/dummy/config/environment.rb create mode 100644 spec/dummy/config/environments/development.rb create mode 100644 spec/dummy/config/environments/production.rb create mode 100644 spec/dummy/config/environments/test.rb create mode 100644 spec/dummy/config/initializers/application_controller_renderer.rb create mode 100644 spec/dummy/config/initializers/assets.rb create mode 100644 spec/dummy/config/initializers/backtrace_silencers.rb create mode 100644 spec/dummy/config/initializers/cookies_serializer.rb create mode 100644 spec/dummy/config/initializers/devise.rb create mode 100644 spec/dummy/config/initializers/filter_parameter_logging.rb create mode 100644 spec/dummy/config/initializers/inflections.rb create mode 100644 spec/dummy/config/initializers/mime_types.rb create mode 100644 spec/dummy/config/initializers/new_framework_defaults.rb create mode 100644 spec/dummy/config/initializers/session_store.rb create mode 100644 spec/dummy/config/initializers/wrap_parameters.rb create mode 100644 spec/dummy/config/locales/devise.en.yml create mode 100644 spec/dummy/config/locales/en.yml create mode 100644 spec/dummy/config/puma.rb create mode 100644 spec/dummy/config/routes.rb create mode 100644 spec/dummy/config/secrets.yml create mode 100644 spec/dummy/config/spring.rb create mode 100644 spec/dummy/db/migrate/20170926045124_create_posts.rb create mode 100644 spec/dummy/db/migrate/20170926045157_create_comments.rb create mode 100644 spec/dummy/db/migrate/20170926045305_devise_create_users.rb create mode 100644 spec/dummy/db/migrate/20170926050413_add_admin_and_role_names_to_users.rb create mode 100644 spec/dummy/db/schema.rb create mode 100644 spec/dummy/lib/assets/.keep create mode 100644 spec/dummy/log/.keep create mode 100644 spec/dummy/public/404.html create mode 100644 spec/dummy/public/422.html create mode 100644 spec/dummy/public/500.html create mode 100644 spec/dummy/public/apple-touch-icon-precomposed.png create mode 100644 spec/dummy/public/apple-touch-icon.png create mode 100644 spec/dummy/public/favicon.ico create mode 100644 spec/factories/comments.rb create mode 100644 spec/factories/posts.rb create mode 100644 spec/factories/users.rb create mode 100644 spec/lib/dunlop/ember/api_base_controller_spec.rb create mode 100644 spec/rails_helper.rb create mode 100644 spec/routing/app_routing_spec.rb create mode 100644 spec/services/flat_keys_spec.rb create mode 100644 spec/spec_helper.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aae7f11 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.bundle/ +log/*.log +pkg/ +spec/dummy/db/*.sqlite3 +spec/dummy/db/*.sqlite3-journal +spec/dummy/log/*.log +spec/dummy/tmp/ diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..a35c44f --- /dev/null +++ b/.rspec @@ -0,0 +1 @@ +--require rails_helper diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..bc174f8 --- /dev/null +++ b/Gemfile @@ -0,0 +1,32 @@ +source 'https://rubygems.org' + +# Declare your gem's dependencies in dunlop-ember.gemspec. +# Bundler will treat runtime dependencies like base dependencies, and +# development dependencies will be added by default to the :development group. +gemspec + +gem 'coffee-rails' +gem 'kaminari' + +group :development, :test do + gem 'rack-cors' + gem 'pry-rails' + gem 'pry-doc' + gem 'spring' + gem 'spring-commands-rspec' + gem 'rspec-rails' + gem 'cancancan' + gem 'slim-rails' + gem 'dunlop-core', github: 'companytools/dunlop-core', branch: 'master' + #gem 'dunlop-core', path: '~/development/rails/components/dunlop-core' + gem 'factory_girl_rails' + gem 'active_model_serializers' + gem 'database_cleaner' +end +# Declare any dependencies that are still in development here instead of in +# your gemspec. These might include edge Rails or gems from your path or +# Git. Remember to move these dependencies to your gemspec before releasing +# your gem to rubygems.org. + +# To use a debugger +# gem 'byebug', group: [:development, :test] diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..23f5365 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,332 @@ +GIT + remote: git://github.com/companytools/dunlop-core.git + revision: a7b86d3c17309d9de29bc2b4aa9a7dff842d619f + branch: master + specs: + dunlop-core (1.4.0) + cancancan + carrierwave + coffee-rails (~> 4.1) + devise + devise-token_authenticatable + exception_notification + facets + font-awesome-rails + js-routes + memoist + momentjs-rails + pickadate-rails (~> 3.5.5.0) + rails (>= 4.2.6) + ransack + record_collection (>= 0.10.4) + redcarpet + request_store + responders + sass-rails (>= 5.0.4) + simple_form + slim-rails + state_machines-activerecord + +PATH + remote: . + specs: + dunlop-ember (0.1.0) + active_model_serializers + devise + rails (>= 4.2.0) + ransack + +GEM + remote: https://rubygems.org/ + specs: + actioncable (5.1.4) + actionpack (= 5.1.4) + nio4r (~> 2.0) + websocket-driver (~> 0.6.1) + actionmailer (5.1.4) + actionpack (= 5.1.4) + actionview (= 5.1.4) + activejob (= 5.1.4) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (5.1.4) + actionview (= 5.1.4) + activesupport (= 5.1.4) + rack (~> 2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.1.4) + activesupport (= 5.1.4) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + active_attr (0.10.2) + activemodel (>= 3.0.2, < 5.2) + activesupport (>= 3.0.2, < 5.2) + active_model_serializers (0.10.6) + actionpack (>= 4.1, < 6) + activemodel (>= 4.1, < 6) + case_transform (>= 0.2) + jsonapi-renderer (>= 0.1.1.beta1, < 0.2) + activejob (5.1.4) + activesupport (= 5.1.4) + globalid (>= 0.3.6) + activemodel (5.1.4) + activesupport (= 5.1.4) + activerecord (5.1.4) + activemodel (= 5.1.4) + activesupport (= 5.1.4) + arel (~> 8.0) + activesupport (5.1.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (~> 0.7) + minitest (~> 5.1) + tzinfo (~> 1.1) + addressable (2.5.2) + public_suffix (>= 2.0.2, < 4.0) + arel (8.0.0) + bcrypt (3.1.11) + builder (3.2.3) + cancancan (2.0.0) + capybara (2.15.2) + addressable + mini_mime (>= 0.1.3) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (~> 2.0) + carrierwave (1.2.1) + activemodel (>= 4.0.0) + activesupport (>= 4.0.0) + mime-types (>= 1.16) + case_transform (0.2) + activesupport + coderay (1.1.2) + coffee-rails (4.2.2) + coffee-script (>= 2.2.0) + railties (>= 4.0.0) + coffee-script (2.4.1) + coffee-script-source + execjs + coffee-script-source (1.12.2) + concurrent-ruby (1.0.5) + crass (1.0.2) + database_cleaner (1.6.1) + devise (4.3.0) + bcrypt (~> 3.0) + orm_adapter (~> 0.1) + railties (>= 4.1.0, < 5.2) + responders + warden (~> 1.2.3) + devise-token_authenticatable (1.0.0) + devise (>= 4.0.0, < 4.4.0) + diff-lcs (1.3) + erubi (1.6.1) + exception_notification (4.2.2) + actionmailer (>= 4.0, < 6) + activesupport (>= 4.0, < 6) + execjs (2.7.0) + facets (3.1.0) + factory_girl (4.8.1) + activesupport (>= 3.0.0) + factory_girl_rails (4.8.0) + factory_girl (~> 4.8.0) + railties (>= 3.0.0) + ffi (1.9.18) + font-awesome-rails (4.7.0.2) + railties (>= 3.2, < 5.2) + globalid (0.4.0) + activesupport (>= 4.2.0) + i18n (0.8.6) + js-routes (1.4.2) + railties (>= 3.2) + sprockets-rails + jsonapi-renderer (0.1.3) + kaminari (1.0.1) + activesupport (>= 4.1.0) + kaminari-actionview (= 1.0.1) + kaminari-activerecord (= 1.0.1) + kaminari-core (= 1.0.1) + kaminari-actionview (1.0.1) + actionview + kaminari-core (= 1.0.1) + kaminari-activerecord (1.0.1) + activerecord + kaminari-core (= 1.0.1) + kaminari-core (1.0.1) + loofah (2.1.1) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.6.6) + mime-types (>= 1.16, < 4) + memoist (0.16.0) + method_source (0.9.0) + mime-types (3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2016.0521) + mini_mime (0.1.4) + mini_portile2 (2.3.0) + minitest (5.10.3) + momentjs-rails (2.17.1) + railties (>= 3.1) + nio4r (2.1.0) + nokogiri (1.8.1) + mini_portile2 (~> 2.3.0) + orm_adapter (0.5.0) + pickadate-rails (3.5.5.0) + railties (>= 3.1.0) + polyamorous (1.3.1) + activerecord (>= 3.0) + pry (0.11.1) + coderay (~> 1.1.0) + method_source (~> 0.9.0) + pry-doc (0.11.1) + pry (~> 0.9) + yard (~> 0.9) + pry-rails (0.3.6) + pry (>= 0.10.4) + public_suffix (3.0.0) + rack (2.0.3) + rack-cors (1.0.1) + rack-test (0.7.0) + rack (>= 1.0, < 3) + rails (5.1.4) + actioncable (= 5.1.4) + actionmailer (= 5.1.4) + actionpack (= 5.1.4) + actionview (= 5.1.4) + activejob (= 5.1.4) + activemodel (= 5.1.4) + activerecord (= 5.1.4) + activesupport (= 5.1.4) + bundler (>= 1.3.0) + railties (= 5.1.4) + sprockets-rails (>= 2.0.0) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.0.3) + loofah (~> 2.0) + railties (5.1.4) + actionpack (= 5.1.4) + activesupport (= 5.1.4) + method_source + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + rake (12.1.0) + ransack (1.8.3) + actionpack (>= 3.0) + activerecord (>= 3.0) + activesupport (>= 3.0) + i18n + polyamorous (~> 1.3) + rb-fsevent (0.10.2) + rb-inotify (0.9.10) + ffi (>= 0.5.0, < 2) + record_collection (0.10.4) + active_attr (>= 0.8) + activemodel (>= 4.1) + railties (>= 3.1) + redcarpet (3.4.0) + request_store (1.3.2) + responders (2.4.0) + actionpack (>= 4.2.0, < 5.3) + railties (>= 4.2.0, < 5.3) + rspec-core (3.6.0) + rspec-support (~> 3.6.0) + rspec-expectations (3.6.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.6.0) + rspec-mocks (3.6.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.6.0) + rspec-rails (3.6.1) + actionpack (>= 3.0) + activesupport (>= 3.0) + railties (>= 3.0) + rspec-core (~> 3.6.0) + rspec-expectations (~> 3.6.0) + rspec-mocks (~> 3.6.0) + rspec-support (~> 3.6.0) + rspec-support (3.6.0) + sass (3.5.3) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sass-rails (5.0.7) + railties (>= 4.0.0, < 6) + sass (~> 3.1) + sprockets (>= 2.8, < 4.0) + sprockets-rails (>= 2.0, < 4.0) + tilt (>= 1.1, < 3) + simple_form (3.5.0) + actionpack (> 4, < 5.2) + activemodel (> 4, < 5.2) + slim (3.0.8) + temple (>= 0.7.6, < 0.9) + tilt (>= 1.3.3, < 2.1) + slim-rails (3.1.2) + actionpack (>= 3.1) + railties (>= 3.1) + slim (~> 3.0) + spring (2.0.2) + activesupport (>= 4.2) + spring-commands-rspec (1.0.4) + spring (>= 0.9.1) + sprockets (3.7.1) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.2.1) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + sqlite3 (1.3.13) + state_machines (0.5.0) + state_machines-activemodel (0.5.0) + activemodel (>= 4.1, < 5.2) + state_machines (>= 0.5.0) + state_machines-activerecord (0.5.0) + activerecord (>= 4.1, < 5.2) + state_machines-activemodel (>= 0.5.0) + temple (0.8.0) + thor (0.20.0) + thread_safe (0.3.6) + tilt (2.0.8) + tzinfo (1.2.3) + thread_safe (~> 0.1) + warden (1.2.7) + rack (>= 1.0) + websocket-driver (0.6.5) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.2) + xpath (2.1.0) + nokogiri (~> 1.3) + yard (0.9.9) + +PLATFORMS + ruby + +DEPENDENCIES + active_model_serializers + cancancan + capybara + coffee-rails + database_cleaner + dunlop-core! + dunlop-ember! + factory_girl_rails + kaminari + pry-doc + pry-rails + rack-cors + rspec-rails + slim-rails + spring + spring-commands-rspec + sqlite3 + +BUNDLED WITH + 1.16.0 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9912c5b --- /dev/null +++ b/LICENSE @@ -0,0 +1 @@ +Copyright 2016 Companytools diff --git a/README.md b/README.md new file mode 100644 index 0000000..57cf0f5 --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +# Dunlop::Ember +This gem adds some context and support for connection ember applications +## baic assumptions (for now (infrastructure is growing)) +* The model structure is non namespaced with `api` +* The controllers have namespace `Api`, not versioned (controller level) api (yet): + ```ruby + namespace :api, path: 'api/v1' do + # ...api controller definitions... + end + ``` +* The inheritance column for STI models is `sti_type` in stead of the + inconvenient chosen `type`: + ```ruby + class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true + self.inheritance_column = :sti_type + end + ``` +* There is a UserSerializer in the main_app, can be same as `Api::User` + serializer `app/serializers/user_serializer.rb`: + ```ruby + class UserSerializer < Api::UserSerializer + # attribute :email + # attribute :nickname + end + ``` + + +## Installation +Add this line to your application's Gemfile: + +```ruby +gem 'dunlop-ember' +``` + +And then execute: +```bash +$ bundle +``` + +Add the engine to your routes file +```ruby + mount Dunlop::Ember::Engine => '/app' +``` diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..78952ef --- /dev/null +++ b/Rakefile @@ -0,0 +1,26 @@ +begin + require 'bundler/setup' +rescue LoadError + puts 'You must `gem install bundler` and `bundle install` to run rake tasks' +end + +require 'rdoc/task' + +RDoc::Task.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'Dunlop::Ember' + rdoc.options << '--line-numbers' + rdoc.rdoc_files.include('README.md') + rdoc.rdoc_files.include('lib/**/*.rb') +end + +APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__) +load 'rails/tasks/engine.rake' + + +load 'rails/tasks/statistics.rake' + + + +require 'bundler/gem_tasks' + diff --git a/app/assets/config/dunlop_ember_manifest.js b/app/assets/config/dunlop_ember_manifest.js new file mode 100644 index 0000000..57a6fd1 --- /dev/null +++ b/app/assets/config/dunlop_ember_manifest.js @@ -0,0 +1,2 @@ +//= link_directory ../javascripts/dunlop/ember .js +//= link_directory ../stylesheets/dunlop/ember .css diff --git a/app/assets/images/dunlop/ember/.keep b/app/assets/images/dunlop/ember/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/assets/javascripts/dunlop/ember/application.js b/app/assets/javascripts/dunlop/ember/application.js new file mode 100644 index 0000000..e54c646 --- /dev/null +++ b/app/assets/javascripts/dunlop/ember/application.js @@ -0,0 +1,13 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, +// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. JavaScript code in this file should be added after the last require_* statement. +// +// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details +// about supported directives. +// +//= require_tree . diff --git a/app/assets/stylesheets/dunlop/ember/application.css b/app/assets/stylesheets/dunlop/ember/application.css new file mode 100644 index 0000000..0ebd7fe --- /dev/null +++ b/app/assets/stylesheets/dunlop/ember/application.css @@ -0,0 +1,15 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. + * + *= require_tree . + *= require_self + */ diff --git a/app/controllers/dunlop/ember/application_controller.rb b/app/controllers/dunlop/ember/application_controller.rb new file mode 100644 index 0000000..2f222db --- /dev/null +++ b/app/controllers/dunlop/ember/application_controller.rb @@ -0,0 +1,54 @@ +module Dunlop + module Ember + class ApplicationController < ActionController::Base + protect_from_forgery with: :exception + before_action :authenticate_user_from_token! + before_action :authenticate_user! + + def ember_path + app_globals = {} + if adapter_name = params[:adapter].to_s.scan(/\w+/).first.presence + app_index = Rails.root.join("public/adapters/#{adapter_name}/app/index.html") + return render text: 'unauthorized, no adapter engine', status: 403 unless adapter = Panda.adapters[adapter_name] + #app_globals = adapter.settings # load through request instead. More stable then changing environments + unless Rails.application.config.try(:loose_ember_app_authorization) + return render text: 'unauthorized, no adapter engine', status: 403 unless current_user.admin? or authorize!(:read, adapter.engine) + end + else + app_index = Rails.root.join('public/app/index.html') + end + Rails.logger.info "Loading ember app for path '#/#{params[:rest]}' adapter: '#{params[:adapter].presence || 'main_app'}'" + if app_index.exist? + index_html = app_index.read.to_s + app_globals[:flash] = flash.to_h if flash.present? + index_html.sub! 'app_globals={}', "app_globals=#{app_globals.to_json}" if app_globals.present? + render html: index_html.html_safe + else + render html: "App file #{app_index} not found".html_safe + end + end + + rescue_from CanCan::AccessDenied do + if request.format.json? + head 403 + else + render 'application/403', status: 403 + end + end + + private + + def authenticate_user_from_token! + # https://romulomachado.github.io/2015/09/28/using-ember-simple-auth-with-devise.html + authenticate_with_http_token do |token, options| + user_email = options[:email].presence + user = user_email && User.find_by_email(user_email) + + if user && Devise.secure_compare(user.authentication_token, token) + sign_in user, store: false + end + end + end + end + end +end diff --git a/app/controllers/dunlop/ember/sessions_controller.rb b/app/controllers/dunlop/ember/sessions_controller.rb new file mode 100644 index 0000000..7c3aeae --- /dev/null +++ b/app/controllers/dunlop/ember/sessions_controller.rb @@ -0,0 +1,27 @@ +class Dunlop::Ember::SessionsController < Devise::SessionsController + #respond_to :json + skip_before_action :verify_authenticity_token, if: :json_request?, raise: false + + #https://www.devmynd.com/blog/2014-7-rails-ember-js-with-the-ember-cli-redux-part-1-the-api-and-cms-with-ruby-on-rails/ + def create + if json_request? + super do |user| + data = { + token: user.authentication_token, + email: user.email, + user_id: user.id + } + render json: data, status: 201 and return + end + else + super + end + end + + protected + + def json_request? + request.format.json? + end +end + diff --git a/app/controllers/dunlop/ember/users_controller.rb b/app/controllers/dunlop/ember/users_controller.rb new file mode 100644 index 0000000..c7a9e04 --- /dev/null +++ b/app/controllers/dunlop/ember/users_controller.rb @@ -0,0 +1,16 @@ +module Dunlop::Ember + class UsersController < Dunlop::Ember::ApplicationController + def me + if respond_to?(:current_user) and current_user.present? + user = current_user + sign_out user # no more current_user, needed to allow sign_in using store: true to work (devise v4.3.0) + sign_in user, store: true # create session if not exist, only needed for hybrid rails/api integrations like ePOTS. Otherwise api only without store is sufficient + #sign_in current_user, store: true # create session if not exist, only needed for hybrid rails/api integrations like ePOTS. Otherwise api only without store is sufficient + #warden.set_user current_user, store: true + render json: current_user, serializer: UserSerializer + else + head 404 + end + end + end +end diff --git a/app/helpers/dunlop/ember/application_helper.rb b/app/helpers/dunlop/ember/application_helper.rb new file mode 100644 index 0000000..d15ac06 --- /dev/null +++ b/app/helpers/dunlop/ember/application_helper.rb @@ -0,0 +1,6 @@ +module Dunlop + module Ember + module ApplicationHelper + end + end +end diff --git a/app/jobs/dunlop/ember/application_job.rb b/app/jobs/dunlop/ember/application_job.rb new file mode 100644 index 0000000..8d7423a --- /dev/null +++ b/app/jobs/dunlop/ember/application_job.rb @@ -0,0 +1,6 @@ +module Dunlop + module Ember + class ApplicationJob < ActiveJob::Base + end + end +end diff --git a/app/mailers/dunlop/ember/application_mailer.rb b/app/mailers/dunlop/ember/application_mailer.rb new file mode 100644 index 0000000..a32cab7 --- /dev/null +++ b/app/mailers/dunlop/ember/application_mailer.rb @@ -0,0 +1,8 @@ +module Dunlop + module Ember + class ApplicationMailer < ActionMailer::Base + default from: 'from@example.com' + layout 'mailer' + end + end +end diff --git a/app/services/flat_keys.rb b/app/services/flat_keys.rb new file mode 100644 index 0000000..1b91bb1 --- /dev/null +++ b/app/services/flat_keys.rb @@ -0,0 +1,51 @@ +# Transform a nested tructure indicated by dots to a structure as used by the ActiveRecord includes statement +# - dslams +# - ppls.distribution_cables +# => +# [:dslams, {ppls: :distribution_cables}] +class FlatKeys + class << self + + def as_nested_structure(ary) + return ary unless ary.first.is_a?(String) + nested_keys, flat_keys = ary.partition{|spec| spec['.']} + result = flat_keys.map(&:to_sym) + if nested_keys.any? + obj = {} + nested_keys.map{ |key| key.split('.').map(&:to_sym) }.each do |parts| + traverse_nest_structure(parts, obj) + end + result.push obj + end + result + end + + def traverse_nest_structure(parts, obj) + key = parts.shift + if parts.size == 1 + case obj[key] + when nil then obj[key] = parts[0] + when Array then obj[key] |= [parts[0]] + when Hash + raise "Colliding keys for nesting of #{key} -> #{parts[0]}" unless obj[key].has_key?(parts[0]) + else # expect symbol + obj[key] = Array.wrap(obj[key]).push parts[0] unless obj[key] == parts[0] # no duplicate + end + else # parts.size > 2 + case obj[key] + when nil + obj[key] = {} + traverse_nest_structure(parts, obj[key]) + when Array + raise "Cannot traverse #{key} -> #{parts.join('.')} because existing array value #{obj[key].inspect}" + when Hash + traverse_nest_structure(parts, obj[key]) + else # expect symbol + raise "Cannot add deeper nesting for endpoing with different name #{key} -> #{obj[key]} => #{parts.join('.')}" unless obj[key] = parts[0] # same name, allows deeper nesting + obj[key] = {obj[key] => nil} # prepare for nesting + traverse_nest_structure(parts, obj[key]) + end + end + end + end +end diff --git a/app/views/dunlop/ember/application/ember_path.html.slim b/app/views/dunlop/ember/application/ember_path.html.slim new file mode 100644 index 0000000..a12ef33 --- /dev/null +++ b/app/views/dunlop/ember/application/ember_path.html.slim @@ -0,0 +1,4 @@ +h3 + span Could not find + tt= '/app/index.html' + span file diff --git a/app/views/layouts/dunlop/ember/application.html.erb b/app/views/layouts/dunlop/ember/application.html.erb new file mode 100644 index 0000000..880df0d --- /dev/null +++ b/app/views/layouts/dunlop/ember/application.html.erb @@ -0,0 +1,14 @@ + + + + Dunlop ember + <%= stylesheet_link_tag "dunlop/ember/application", media: "all" %> + <%= javascript_include_tag "dunlop/ember/application" %> + <%= csrf_meta_tags %> + + + +<%= yield %> + + + diff --git a/bin/rails b/bin/rails new file mode 100755 index 0000000..a4bf0ba --- /dev/null +++ b/bin/rails @@ -0,0 +1,13 @@ +#!/usr/bin/env ruby +# This command will automatically be run when you run "rails" with Rails gems +# installed from the root of your application. + +ENGINE_ROOT = File.expand_path('../..', __FILE__) +ENGINE_PATH = File.expand_path('../../lib/dunlop/ember/engine', __FILE__) + +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) + +require 'rails/all' +require 'rails/engine/commands' diff --git a/config/initializers/active_model_serializers_config.rb b/config/initializers/active_model_serializers_config.rb new file mode 100644 index 0000000..c622aef --- /dev/null +++ b/config/initializers/active_model_serializers_config.rb @@ -0,0 +1,7 @@ +if defined?(ActiveModelSerializers) + ActiveModelSerializers.config.adapter = :json_api # Default: `:attributes` + #ActiveModelSerializers.config.key_transform = :unaltered # explicitly set because json api moves to dash + ActiveModelSerializers.config.jsonapi_pagination_links_enabled = false # manual meta setting + ActiveModelSerializers.config.jsonapi_namespace_separator = '/' # Default: `:attributes` + ActiveModelSerializers.config.jsonapi_resource_type = :singular +end diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 0000000..ee73810 --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,8 @@ +Dunlop::Ember::Engine.routes.draw do + get 'users/me' + devise_scope :user do + post 'users/sign_in', to: 'sessions#create' + end + root to: 'application#ember_path' + get '*rest', controller: 'application', action: 'ember_path' +end diff --git a/config/spring.rb b/config/spring.rb new file mode 100644 index 0000000..6b95e4d --- /dev/null +++ b/config/spring.rb @@ -0,0 +1 @@ +Spring.application_root = './spec/dummy' diff --git a/dunlop-ember.gemspec b/dunlop-ember.gemspec new file mode 100644 index 0000000..2b74499 --- /dev/null +++ b/dunlop-ember.gemspec @@ -0,0 +1,29 @@ +$:.push File.expand_path("../lib", __FILE__) + +# Maintain your gem's version: +require "dunlop/ember/version" + +# Describe your gem and declare its dependencies: +Gem::Specification.new do |s| + s.name = "dunlop-ember" + s.version = Dunlop::Ember::VERSION + s.authors = ["Companytools"] + s.email = ["develop@companytools.nl"] + s.homepage = "http://companytools.nl" + s.summary = "Summary of Dunlop::Ember." + s.description = "Description of Dunlop::Ember." + s.license = "COMPANYTOOLS" + + s.files = Dir["{app,config,db,lib}/**/*", "LICENSE", "Rakefile", "README.md"] + s.test_files = Dir["spec/**/*"] + + s.add_dependency "rails", ">= 4.2.0" + s.add_dependency "ransack" + s.add_dependency "devise" + s.add_dependency "active_model_serializers" + + s.add_development_dependency "sqlite3" + s.add_development_dependency 'rspec-rails' + s.add_development_dependency 'capybara' + s.add_development_dependency 'factory_girl_rails' +end diff --git a/lib/dunlop/ember.rb b/lib/dunlop/ember.rb new file mode 100644 index 0000000..1f9d5ac --- /dev/null +++ b/lib/dunlop/ember.rb @@ -0,0 +1,9 @@ +require "dunlop/ember/engine" +require "dunlop/ember/cancan_safeguard" +require "dunlop/ember/api_base_controller" + +module Dunlop + module Ember + # Your code goes here... + end +end diff --git a/lib/dunlop/ember/api_base_controller.rb b/lib/dunlop/ember/api_base_controller.rb new file mode 100644 index 0000000..bc6193a --- /dev/null +++ b/lib/dunlop/ember/api_base_controller.rb @@ -0,0 +1,252 @@ +module Dunlop::Ember::ApiBaseController + extend ActiveSupport::Concern + + included do + before_action :authenticate_user_from_token! + before_action :authenticate_user! + before_action :set_current_user + before_action :find_record, only: %i[show update destroy] + respond_to :json + rescue_from CanCan::AccessDenied do + render json: {errors: [{status: 403, detail: 'unauthorized'}]}, status: 403 + end + end + + def index + index_safeguard record_class + result = record_scope.search(query).result + result = result.includes(*FlatKeys.as_nested_structure(index_include_relations)) if index_include_relations.present? + result = result.uniq if params[:uniq].present? + if index_pagination? + paginated = result.page(params[:page]).per(params[:per_page]) + render json: paginated, meta: {total_pages: paginated.total_pages, total_count: paginated.total_count} + else + render json: result + end + end + + def show + show_safeguard @record + render json: @record + end + + def create + @record ||= record_class.new(record_params) + create_safeguard @record + return if performed? + if @record.save + render json: @record + else + render json: {errors: @record.errors.map{|attr, errors| {attr => errors.to_s}}}, status: :unprocessable_entity + end + end + + def update + update_safeguard @record + return if performed? + @record.update_attributes record_params + render json: @record + end + + def destroy + destroy_safeguard @record + @record.destroy + head :no_content + end + + private + + # used to include relations on database lookup + # has form: + # ['comments.replies', 'authors.orginizations'] + # + def include_relations + return [] unless includes = params[:include].presence + includes.split(',') + end + + %i[index show].each do |action| + define_method "#{action}_include_relations" do + include_relations + end + end + + def publish(event, data = {}) + return + data = data.merge(event: event) + data[:client_id] = request.headers['HTTP_CLIENT_ID'] if request.present? + FayeRails.client(nil).publish('/activity', data) + end + + def index_safeguard(model) + # can be overloaded + end + + def show_safeguard(record) + # can be overloaded + record_safeguard(record) + end + + def create_safeguard(record) + # can be overloaded + record_safeguard(record) + end + + def update_safeguard(record) + # can be overloaded + record_safeguard(record) + end + + def destroy_safeguard(record) + # can be overloaded + record_safeguard(record) + end + + def record_safeguard(record) + # can be overloaded + return + render json: {}, status: :unauthorized unless authorized_ids(record).include?(current_user.id) + end + + def authorized_ids(*) + # can be overloaded + [] + end + + def authenticate_user_from_token! + # https://romulomachado.github.io/2015/09/28/using-ember-simple-auth-with-devise.html + authenticate_with_http_token do |token, options| + user_email = options[:email].presence + user = user_email && User.find_by_email(user_email) + + if user && Devise.secure_compare(user.authentication_token, token) + sign_in user, store: false + end + end + end + + public def record_class + deducted_class_name = controller_path.sub(/api\//,'').classify + deducted_class_name.safe_constantize || deducted_class_name.demodulize.constantize + end + + # basic scope for find and index. Can be overloaded to add extra security restrictions + def record_scope + record_class.all + end + + def find_record(options = {}) + scope = record_scope + scope = scope.includes(*Array.wrap(options[:includes])) if options[:includes] + @record = scope.find(params[:id]) + end + + def record_params + #params.require(controller_path.sub(/^api\//, '').singularize).permit(*permitted_params) + params.require(controller_path.sub(/api\//, '').singularize).permit(*permitted_params) + end + + def permitted_params + [] + end + + # used for serialization + def serialize_options + return {} unless includes = params[:include].presence + {include: includes.split(',')} + end + + # map action specific serialize options to general serialize options + %i[index show create update].each do |action| + define_method "#{action}_serialize_options" do + serialize_options + end + end + + # /(_eq|_eq_any|_eq_all|_not_eq|_not_eq_any|_not_eq_all|_matches|_matches_any|_matches_all| + # _does_not_match|_does_not_match_any|_does_not_match_all|_lt|_lt_any|_lt_all|_lteq|_lteq_any| + # _lteq_all|_gt|_gt_any|_gt_all|_gteq|_gteq_any|_gteq_all|_in|_in_any|_in_all|_not_in|_not_in_any| + # _not_in_all|_cont|_cont_any|_cont_all|_i_cont|_i_cont_any|_i_cont_all|_not_cont|_not_cont_any| + # _not_cont_all|_i_not_cont|_i_not_cont_any|_i_not_cont_all|_start|_start_any|_start_all|_not_start| + # _not_start_any|_not_start_all|_end|_end_any|_end_all|_not_end|_not_end_any|_not_end_all| + # _true|_not_true|_false|_not_false|_present|_blank|_null|_not_null)$/ + PREDICATE_END_MATCHER = Regexp.new("(_#{Ransack.predicates.keys.join('|_')})$") + + #TODO: make me pretty, specs are in place + def query + mapped_query = {} + (params[:q] || {}).each do |key, value| + key = "#{key}_eq" unless %w[s sorts].include?(key) or record_class.try(:ransackable_scopes).try(:include?, key.to_sym) or key =~ PREDICATE_END_MATCHER # expect equality when no predicate is given + if key =~ /^type_/ + # map type to sti_type + mapped_value = case value + when Array then value.map{|v| "#{record_class.name}::#{v.to_s.gsub('-', '_').classify}"} + else + "#{record_class.name}::#{value.to_s.gsub('-', '_').classify}" + end + mapped_query["sti_#{key}"] = mapped_value + else + mapped_query[key] = value + end + end + mapped_query + end + + def _render_with_renderer_json(resource, options = {}) + return resource.to_json if resource.is_a?(Hash) + return resource if resource.is_a?(String) + + action_serialize_options_method = :"#{action_name}_serialize_options" + #action_serialize_options = respond_to?(action_serialize_options_method) ? __send__(action_serialize_options_method) : {} + action_serialize_options = __send__(action_serialize_options_method) rescue {} + action_serialize_options[:include] = options[:include] if options.has_key?(:include) + action_serialize_options[:meta] = options[:meta] if options.has_key?(:meta) + + serializer_class = if options.has_key?(:serializer) + options.delete(:serializer) + elsif action_serialize_options[:serializer].present? + action_serialize_options[:serializer] + elsif resource.is_a?(ActiveRecord::Base) + #infer based on controller path replacing actual controller part with resouce part /workflow_step_definitions/:id/table + "#{self.class.name.deconstantize}::#{resource.class.name.demodulize}Serializer".constantize + elsif resource.is_a?(Array) and resource.first.is_a?(ActiveRecord::Base) + # infer based in first element of collection + "#{self.class.name.deconstantize}::#{resource.first.class.name.demodulize}Serializer".constantize + else + # infer based on controller path + "#{controller_path.underscore.classify}Serializer".constantize + end + + serializer = if resource.respond_to?(:each) + ActiveModel::Serializer::CollectionSerializer.new(resource, action_serialize_options.merge(serializer: serializer_class)) #TODO: fix index includes + else + serializer_class.new(resource, action_serialize_options) + end + adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, action_serialize_options) + res = {} + time = Benchmark.ms { res = adapter.as_json } + logger.info "Generated serialized output in #{time.round} ms" + #binding.pry + #return res + return res.is_a?(String) ? res : res.to_json + end + + def has_permission_of_type(type, user = current_user) + Dunlop::Ability.has_permission_of_type(type, user) + end + + def any_permission_starts_with(expression, user = current_user) + Dunlop::Ability.any_permission_starts_with(expression, user) + end + + def index_pagination? + true + end + + def set_current_user + request.env["exception_notifier.exception_data"] = { + current_user: current_user.try(:inspect) + } + User.current = current_user + end +end diff --git a/lib/dunlop/ember/cancan_safeguard.rb b/lib/dunlop/ember/cancan_safeguard.rb new file mode 100644 index 0000000..8744767 --- /dev/null +++ b/lib/dunlop/ember/cancan_safeguard.rb @@ -0,0 +1,22 @@ +module Dunlop::Ember::CanCanSafeguard + def index_safeguard(model) + authorize! :index, model + end + + def show_safeguard(record) + authorize! :show, record + end + + def create_safeguard(record) + authorize! :create, record + end + + def update_safeguard(record) + authorize! :update, record + end + + def destroy_safeguard(record) + authorize! :destroy, record + end + +end diff --git a/lib/dunlop/ember/engine.rb b/lib/dunlop/ember/engine.rb new file mode 100644 index 0000000..10ce68d --- /dev/null +++ b/lib/dunlop/ember/engine.rb @@ -0,0 +1,14 @@ +require 'devise' +require 'ransack' +require 'active_model_serializers' + +module Dunlop + module Ember + class Engine < ::Rails::Engine + isolate_namespace Dunlop::Ember + config.generators do |g| + g.test_framework :rspec + end + end + end +end diff --git a/lib/dunlop/ember/version.rb b/lib/dunlop/ember/version.rb new file mode 100644 index 0000000..7c54301 --- /dev/null +++ b/lib/dunlop/ember/version.rb @@ -0,0 +1,5 @@ +module Dunlop + module Ember + VERSION = '0.1.0' + end +end diff --git a/lib/generators/dunlop/ember/install/USAGE b/lib/generators/dunlop/ember/install/USAGE new file mode 100644 index 0000000..c9fb09f --- /dev/null +++ b/lib/generators/dunlop/ember/install/USAGE @@ -0,0 +1,8 @@ +Description: + Explain the generator + +Example: + rails generate install Thing + + This will create: + what/will/it/create diff --git a/lib/generators/dunlop/ember/install/install_generator.rb b/lib/generators/dunlop/ember/install/install_generator.rb new file mode 100644 index 0000000..8448b96 --- /dev/null +++ b/lib/generators/dunlop/ember/install/install_generator.rb @@ -0,0 +1,10 @@ +class Dunlop::Ember::InstallGenerator < Rails::Generators::Base + source_root File.expand_path('../templates', __FILE__) + + def add_initializers + directory 'initializers', 'config/initializers' + end + def upgrade_devise + gsub_file Rails.root.join('config/routes.rb'), /devise_for :users$/, "devise_for :users, controllers: {sessions: 'dunlop/ember/sessions'}" + end +end diff --git a/lib/generators/dunlop/ember/install/templates/initializers/active_model_serializers_config.rb b/lib/generators/dunlop/ember/install/templates/initializers/active_model_serializers_config.rb new file mode 100644 index 0000000..49959ca --- /dev/null +++ b/lib/generators/dunlop/ember/install/templates/initializers/active_model_serializers_config.rb @@ -0,0 +1,5 @@ +ActiveModelSerializers.config.adapter = :json_api # Default: `:attributes` +#ActiveModelSerializers.config.key_transform = :unaltered # explicitly set because json api moves to dash +ActiveModelSerializers.config.jsonapi_pagination_links_enabled = false # manual meta setting +ActiveModelSerializers.config.jsonapi_namespace_separator = '/' # Default: `:attributes` +ActiveModelSerializers.config.jsonapi_resource_type = :singular diff --git a/lib/generators/dunlop/ember/install/templates/initializers/jsonapi_mime_type.rb b/lib/generators/dunlop/ember/install/templates/initializers/jsonapi_mime_type.rb new file mode 100644 index 0000000..980ff91 --- /dev/null +++ b/lib/generators/dunlop/ember/install/templates/initializers/jsonapi_mime_type.rb @@ -0,0 +1,8 @@ +api_mime_types = %W[ + application/vnd.api+json + text/x-json + application/json +] + +Mime::Type.unregister :json +Mime::Type.register 'application/json', :json, api_mime_types diff --git a/lib/tasks/dunlop/ember_tasks.rake b/lib/tasks/dunlop/ember_tasks.rake new file mode 100644 index 0000000..d2f84d8 --- /dev/null +++ b/lib/tasks/dunlop/ember_tasks.rake @@ -0,0 +1,4 @@ +# desc "Explaining what the task does" +# task :dunlop_ember do +# # Task goes here +# end diff --git a/spec/controllers/api/posts_controller/index_spec.rb b/spec/controllers/api/posts_controller/index_spec.rb new file mode 100644 index 0000000..a9294c4 --- /dev/null +++ b/spec/controllers/api/posts_controller/index_spec.rb @@ -0,0 +1,110 @@ +require 'rails_helper' + +RSpec.describe Api::PostsController, type: :controller do + describe "index" do + describe 'unauthorized' do + it 'redirects to login page' do + get :index + response.redirect_url.should end_with('/users/sign_in') + end + end + + describe 'authorized' do + before { sign_in create :user } + it "no default include, default pagination" do + post1 = create :post, title: 'post-1', body: 'post-body-1' + comment = create :comment, post: post1 + post2 = create :post, title: 'post-2', body: 'post-body-2' + get :index + assert_json( + data: [ + { + id: post1.id.to_s, + type: "post", + attributes: {"title"=>"post-1", "body"=>"post-body-1"}, + relationships: { + comments: {data: [{id: comment.id.to_s , type: "comment" }]} + } + }, + { + id: post2.id.to_s, + type: "post", + attributes: {"title"=>"post-2", "body"=>"post-body-2"}, + relationships: { + comments: {data: []} + } + }, + ], + meta: {"total-pages"=>1, "total-count"=>2} + ) + end + + it "does not paginate when index_pagination? is false" do + expect( subject ).to receive(:index_pagination?).and_return false + post1 = create :post, title: 'post-1', body: 'post-body-1' + comment = create :comment, post: post1 + post2 = create :post, title: 'post-2', body: 'post-body-2' + get :index + assert_json( + data: [ + { + id: post1.id.to_s, + type: "post", + attributes: {"title"=>"post-1", "body"=>"post-body-1"}, + relationships: { + comments: {data: [{id: comment.id.to_s , type: "comment" }]} + } + }, + { + id: post2.id.to_s, + type: "post", + attributes: {"title"=>"post-2", "body"=>"post-body-2"}, + relationships: { + comments: {data: []} + } + }, + ] + ) + end + + it "includes associations if configured" do + expect( subject ).to receive(:index_serialize_options).and_return(include: 'comments') + post1 = create :post, title: 'post-1', body: 'post-body-1' + comment = create :comment, post: post1, body: 'post-1-comment-1' + post2 = create :post, title: 'post-2', body: 'post-body-2' + get :index + assert_json( + data: [ + { + id: post1.id.to_s, + type: "post", + attributes: {"title"=>"post-1", "body"=>"post-body-1"}, + relationships: { + comments: {data: [{id: comment.id.to_s , type: "comment" }]} + } + }, + { + id: post2.id.to_s, + type: "post", + attributes: {"title"=>"post-2", "body"=>"post-body-2"}, + relationships: { + comments: {data: []} + } + }, + ], + included: [ + { + id: comment.id.to_s, + type: "comment", + attributes: {body: "post-1-comment-1"}, + relationships: { + post: {data: {id: post1.id.to_s, type: "posts"}} + } + } + ], + meta: {"total-pages"=>1, "total-count"=>2} + ) + end + end + end +end diff --git a/spec/controllers/api/posts_controller/update_spec.rb b/spec/controllers/api/posts_controller/update_spec.rb new file mode 100644 index 0000000..fc5a259 --- /dev/null +++ b/spec/controllers/api/posts_controller/update_spec.rb @@ -0,0 +1,42 @@ +require 'rails_helper' + +RSpec.describe Api::PostsController, type: :controller do + describe "update" do + describe 'unauthorized' do + it 'redirects to login page' do + patch :update, params: {id: 9} + response.redirect_url.should end_with('/users/sign_in') + end + end + + describe 'authorized' do + before { sign_in create :user } + it "includes associations if configured" do + expect( subject ).to receive(:update_serialize_options).and_return(include: 'comments') + post1 = create :post, title: 'post-1', body: 'post-body-1' + comment = create :comment, post: post1, body: 'post-1-comment-1' + patch :update, params: {id: post1.id, post: {title: 'post-1-updated', body: 'post-body-1-updated'}} + assert_json( + data: { + id: post1.id.to_s, + type: "post", + attributes: {"title"=>"post-1", "body"=>"post-body-1-updated"}, # title not permitted, could be boolean admin + relationships: { + comments: {data: [{id: comment.id.to_s , type: "comment" }]} + } + }, + included: [ + { + id: comment.id.to_s, + type: "comment", + attributes: {body: "post-1-comment-1"}, + relationships: { + post: {data: {id: post1.id.to_s, type: "posts"}} + } + } + ] + ) + end + end + end +end diff --git a/spec/dummy/Rakefile b/spec/dummy/Rakefile new file mode 100644 index 0000000..e85f913 --- /dev/null +++ b/spec/dummy/Rakefile @@ -0,0 +1,6 @@ +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require_relative 'config/application' + +Rails.application.load_tasks diff --git a/spec/dummy/app/assets/config/manifest.js b/spec/dummy/app/assets/config/manifest.js new file mode 100644 index 0000000..e065e1f --- /dev/null +++ b/spec/dummy/app/assets/config/manifest.js @@ -0,0 +1,5 @@ + +//= link_tree ../images +//= link_directory ../javascripts .js +//= link_directory ../stylesheets .css +//= link dunlop_ember_manifest.js diff --git a/spec/dummy/app/assets/images/.keep b/spec/dummy/app/assets/images/.keep new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/app/assets/javascripts/application.js b/spec/dummy/app/assets/javascripts/application.js new file mode 100644 index 0000000..e54c646 --- /dev/null +++ b/spec/dummy/app/assets/javascripts/application.js @@ -0,0 +1,13 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, +// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. JavaScript code in this file should be added after the last require_* statement. +// +// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details +// about supported directives. +// +//= require_tree . diff --git a/spec/dummy/app/assets/javascripts/cable.js b/spec/dummy/app/assets/javascripts/cable.js new file mode 100644 index 0000000..71ee1e6 --- /dev/null +++ b/spec/dummy/app/assets/javascripts/cable.js @@ -0,0 +1,13 @@ +// Action Cable provides the framework to deal with WebSockets in Rails. +// You can generate new channels where WebSocket features live using the rails generate channel command. +// +//= require action_cable +//= require_self +//= require_tree ./channels + +(function() { + this.App || (this.App = {}); + + App.cable = ActionCable.createConsumer(); + +}).call(this); diff --git a/spec/dummy/app/assets/javascripts/channels/.keep b/spec/dummy/app/assets/javascripts/channels/.keep new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/app/assets/javascripts/comments.coffee b/spec/dummy/app/assets/javascripts/comments.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/spec/dummy/app/assets/javascripts/comments.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/spec/dummy/app/assets/stylesheets/application.css b/spec/dummy/app/assets/stylesheets/application.css new file mode 100644 index 0000000..0ebd7fe --- /dev/null +++ b/spec/dummy/app/assets/stylesheets/application.css @@ -0,0 +1,15 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. + * + *= require_tree . + *= require_self + */ diff --git a/spec/dummy/app/channels/application_cable/channel.rb b/spec/dummy/app/channels/application_cable/channel.rb new file mode 100644 index 0000000..d672697 --- /dev/null +++ b/spec/dummy/app/channels/application_cable/channel.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Channel < ActionCable::Channel::Base + end +end diff --git a/spec/dummy/app/channels/application_cable/connection.rb b/spec/dummy/app/channels/application_cable/connection.rb new file mode 100644 index 0000000..0ff5442 --- /dev/null +++ b/spec/dummy/app/channels/application_cable/connection.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Connection < ActionCable::Connection::Base + end +end diff --git a/spec/dummy/app/controllers/api/base_controller.rb b/spec/dummy/app/controllers/api/base_controller.rb new file mode 100644 index 0000000..0eeb269 --- /dev/null +++ b/spec/dummy/app/controllers/api/base_controller.rb @@ -0,0 +1,5 @@ +module Api + class BaseController < ActionController::Base + include Dunlop::Ember::ApiBaseController + end +end diff --git a/spec/dummy/app/controllers/api/posts_controller.rb b/spec/dummy/app/controllers/api/posts_controller.rb new file mode 100644 index 0000000..4b577b8 --- /dev/null +++ b/spec/dummy/app/controllers/api/posts_controller.rb @@ -0,0 +1,7 @@ +module Api + class PostsController < Api::BaseController + def permitted_params + [:body] # title not permitted + end + end +end diff --git a/spec/dummy/app/controllers/application_controller.rb b/spec/dummy/app/controllers/application_controller.rb new file mode 100644 index 0000000..8f5c146 --- /dev/null +++ b/spec/dummy/app/controllers/application_controller.rb @@ -0,0 +1,32 @@ +class ApplicationController < ActionController::Base + # Prevent CSRF attacks by raising an exception. + # For APIs, you may want to use :null_session instead. + protect_from_forgery with: :exception + + before_action :authenticate_user! + + #http://rails-bestpractices.com/posts/2010/08/23/fetch-current-user-in-models + before_action :set_current_user + + rescue_from CanCan::AccessDenied do + render 'application/403', status: 403 + end + + + private + + def set_current_user + request.env["exception_notifier.exception_data"] = { + current_user: current_user.try(:inspect) + } + User.current = current_user + end + + # Return an array of ids given as a param or nil if nothing is supplied + def ids_param + return nil unless ids = params[:ids].presence + @ids_param ||= (ids.is_a?(String) ? ids.split(RecordCollection.ids_separator) : Array.wrap(ids)) + end + helper_method :ids_param + +end diff --git a/spec/dummy/app/controllers/comments_controller.rb b/spec/dummy/app/controllers/comments_controller.rb new file mode 100644 index 0000000..2cfbf95 --- /dev/null +++ b/spec/dummy/app/controllers/comments_controller.rb @@ -0,0 +1,58 @@ +class CommentsController < ApplicationController + before_action :set_comment, only: [:show, :edit, :update, :destroy] + + # GET /comments + def index + @comments = Comment.all + end + + # GET /comments/1 + def show + end + + # GET /comments/new + def new + @comment = Comment.new + end + + # GET /comments/1/edit + def edit + end + + # POST /comments + def create + @comment = Comment.new(comment_params) + + if @comment.save + redirect_to @comment, notice: 'Comment was successfully created.' + else + render :new + end + end + + # PATCH/PUT /comments/1 + def update + if @comment.update(comment_params) + redirect_to @comment, notice: 'Comment was successfully updated.' + else + render :edit + end + end + + # DELETE /comments/1 + def destroy + @comment.destroy + redirect_to comments_url, notice: 'Comment was successfully destroyed.' + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_comment + @comment = Comment.find(params[:id]) + end + + # Only allow a trusted parameter "white list" through. + def comment_params + params.require(:comment).permit(:user_id, :post_id, :body) + end +end diff --git a/spec/dummy/app/controllers/concerns/.keep b/spec/dummy/app/controllers/concerns/.keep new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/app/controllers/posts_controller.rb b/spec/dummy/app/controllers/posts_controller.rb new file mode 100644 index 0000000..a9af96b --- /dev/null +++ b/spec/dummy/app/controllers/posts_controller.rb @@ -0,0 +1,58 @@ +class PostsController < ApplicationController + before_action :set_post, only: [:show, :edit, :update, :destroy] + + # GET /posts + def index + @posts = Post.all + end + + # GET /posts/1 + def show + end + + # GET /posts/new + def new + @post = Post.new + end + + # GET /posts/1/edit + def edit + end + + # POST /posts + def create + @post = Post.new(post_params) + + if @post.save + redirect_to @post, notice: 'Post was successfully created.' + else + render :new + end + end + + # PATCH/PUT /posts/1 + def update + if @post.update(post_params) + redirect_to @post, notice: 'Post was successfully updated.' + else + render :edit + end + end + + # DELETE /posts/1 + def destroy + @post.destroy + redirect_to posts_url, notice: 'Post was successfully destroyed.' + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_post + @post = Post.find(params[:id]) + end + + # Only allow a trusted parameter "white list" through. + def post_params + params.require(:post).permit(:title, :body) + end +end diff --git a/spec/dummy/app/helpers/application_helper.rb b/spec/dummy/app/helpers/application_helper.rb new file mode 100644 index 0000000..de6be79 --- /dev/null +++ b/spec/dummy/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/spec/dummy/app/helpers/comments_helper.rb b/spec/dummy/app/helpers/comments_helper.rb new file mode 100644 index 0000000..0ec9ca5 --- /dev/null +++ b/spec/dummy/app/helpers/comments_helper.rb @@ -0,0 +1,2 @@ +module CommentsHelper +end diff --git a/spec/dummy/app/helpers/posts_helper.rb b/spec/dummy/app/helpers/posts_helper.rb new file mode 100644 index 0000000..a7b8cec --- /dev/null +++ b/spec/dummy/app/helpers/posts_helper.rb @@ -0,0 +1,2 @@ +module PostsHelper +end diff --git a/spec/dummy/app/jobs/application_job.rb b/spec/dummy/app/jobs/application_job.rb new file mode 100644 index 0000000..a009ace --- /dev/null +++ b/spec/dummy/app/jobs/application_job.rb @@ -0,0 +1,2 @@ +class ApplicationJob < ActiveJob::Base +end diff --git a/spec/dummy/app/mailers/application_mailer.rb b/spec/dummy/app/mailers/application_mailer.rb new file mode 100644 index 0000000..286b223 --- /dev/null +++ b/spec/dummy/app/mailers/application_mailer.rb @@ -0,0 +1,4 @@ +class ApplicationMailer < ActionMailer::Base + default from: 'from@example.com' + layout 'mailer' +end diff --git a/spec/dummy/app/models/ability.rb b/spec/dummy/app/models/ability.rb new file mode 100644 index 0000000..3351628 --- /dev/null +++ b/spec/dummy/app/models/ability.rb @@ -0,0 +1,7 @@ +class Ability + include Dunlop::Ability + + def setup_abilities + setup_dunlop_abilities + end +end diff --git a/spec/dummy/app/models/application_record.rb b/spec/dummy/app/models/application_record.rb new file mode 100644 index 0000000..ee7b6d6 --- /dev/null +++ b/spec/dummy/app/models/application_record.rb @@ -0,0 +1,18 @@ +class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true + self.inheritance_column = :sti_type + + if Rails::VERSION::MAJOR < 5 + def saved_changes + changes + end + end + + class << self + def truncate + #connection_pool.with_connection { |c| c.truncate table_name } + delete_all + end + end +end + diff --git a/spec/dummy/app/models/comment.rb b/spec/dummy/app/models/comment.rb new file mode 100644 index 0000000..8b86c56 --- /dev/null +++ b/spec/dummy/app/models/comment.rb @@ -0,0 +1,3 @@ +class Comment < ApplicationRecord + belongs_to :post +end diff --git a/spec/dummy/app/models/concerns/.keep b/spec/dummy/app/models/concerns/.keep new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/app/models/execution_batch.rb b/spec/dummy/app/models/execution_batch.rb new file mode 100644 index 0000000..6805c19 --- /dev/null +++ b/spec/dummy/app/models/execution_batch.rb @@ -0,0 +1,3 @@ +class ExecutionBatch < ApplicationRecord + include Dunlop::ExecutionBatchModel +end diff --git a/spec/dummy/app/models/post.rb b/spec/dummy/app/models/post.rb new file mode 100644 index 0000000..4a0df21 --- /dev/null +++ b/spec/dummy/app/models/post.rb @@ -0,0 +1,3 @@ +class Post < ApplicationRecord + has_many :comments +end diff --git a/spec/dummy/app/models/user.rb b/spec/dummy/app/models/user.rb new file mode 100644 index 0000000..7006d87 --- /dev/null +++ b/spec/dummy/app/models/user.rb @@ -0,0 +1,11 @@ +class User < ApplicationRecord + include Dunlop::UserModel + + # Include default devise modules. Others available are: + # :confirmable, :lockable, :timeoutable and :omniauthable + devise :database_authenticatable, #:token_authenticatable, #:registerable, + :recoverable, :rememberable, :trackable, :validatable + + # To be overridden, with application logic + scope :active, ->{ all } +end diff --git a/spec/dummy/app/serializers/api/comment_serializer.rb b/spec/dummy/app/serializers/api/comment_serializer.rb new file mode 100644 index 0000000..a6385ab --- /dev/null +++ b/spec/dummy/app/serializers/api/comment_serializer.rb @@ -0,0 +1,4 @@ +class Api::CommentSerializer < ActiveModel::Serializer + attribute :body + belongs_to :post +end diff --git a/spec/dummy/app/serializers/api/post_serializer.rb b/spec/dummy/app/serializers/api/post_serializer.rb new file mode 100644 index 0000000..e3adf41 --- /dev/null +++ b/spec/dummy/app/serializers/api/post_serializer.rb @@ -0,0 +1,5 @@ +class Api::PostSerializer < ActiveModel::Serializer + attribute :title + attribute :body + has_many :comments +end diff --git a/spec/dummy/app/views/comments/_form.html.slim b/spec/dummy/app/views/comments/_form.html.slim new file mode 100644 index 0000000..08153bd --- /dev/null +++ b/spec/dummy/app/views/comments/_form.html.slim @@ -0,0 +1,18 @@ += form_for @comment do |f| + - if @comment.errors.any? + #error_explanation + h2 = "#{pluralize(@comment.errors.count, "error")} prohibited this comment from being saved:" + ul + - @comment.errors.full_messages.each do |message| + li = message + + .field + = f.label :user_id + = f.number_field :user_id + .field + = f.label :post_id + = f.number_field :post_id + .field + = f.label :body + = f.text_area :body + .actions = f.submit diff --git a/spec/dummy/app/views/comments/edit.html.slim b/spec/dummy/app/views/comments/edit.html.slim new file mode 100644 index 0000000..7385128 --- /dev/null +++ b/spec/dummy/app/views/comments/edit.html.slim @@ -0,0 +1,8 @@ +h1 Editing comment + +== render 'form' + += link_to 'Show', @comment +' | += link_to 'Back', comments_path + diff --git a/spec/dummy/app/views/comments/index.html.slim b/spec/dummy/app/views/comments/index.html.slim new file mode 100644 index 0000000..68b36ed --- /dev/null +++ b/spec/dummy/app/views/comments/index.html.slim @@ -0,0 +1,25 @@ +h1 Listing comments + +table + thead + tr + th User + th Post + th Body + th + th + th + + tbody + - @comments.each do |comment| + tr + td = comment.user_id + td = comment.post_id + td = comment.body + td = link_to 'Show', comment + td = link_to 'Edit', edit_comment_path(comment) + td = link_to 'Destroy', comment, data: { confirm: 'Are you sure?' }, method: :delete + +br + += link_to 'New Comment', new_comment_path diff --git a/spec/dummy/app/views/comments/new.html.slim b/spec/dummy/app/views/comments/new.html.slim new file mode 100644 index 0000000..b529d2c --- /dev/null +++ b/spec/dummy/app/views/comments/new.html.slim @@ -0,0 +1,5 @@ +h1 New comment + +== render 'form' + += link_to 'Back', comments_path diff --git a/spec/dummy/app/views/comments/show.html.slim b/spec/dummy/app/views/comments/show.html.slim new file mode 100644 index 0000000..6f4640e --- /dev/null +++ b/spec/dummy/app/views/comments/show.html.slim @@ -0,0 +1,15 @@ +p#notice = notice + +p + strong User: + = @comment.user_id +p + strong Post: + = @comment.post_id +p + strong Body: + = @comment.body + += link_to 'Edit', edit_comment_path(@comment) +' | += link_to 'Back', comments_path diff --git a/spec/dummy/app/views/layouts/_messages.html.slim b/spec/dummy/app/views/layouts/_messages.html.slim new file mode 100644 index 0000000..5a6c1ae --- /dev/null +++ b/spec/dummy/app/views/layouts/_messages.html.slim @@ -0,0 +1,5 @@ +- flash.each do |name, msg| + - if msg.is_a?(String) + div.alert-box.round class="#{name.to_s == 'notice' ? 'success' : 'alert'}" data-alert="" + = content_tag :div, msg + a.close href="#" × diff --git a/spec/dummy/app/views/layouts/_navigation.html.slim b/spec/dummy/app/views/layouts/_navigation.html.slim new file mode 100644 index 0000000..220cdfb --- /dev/null +++ b/spec/dummy/app/views/layouts/_navigation.html.slim @@ -0,0 +1,5 @@ +nav.top-bar data-topbar=true + ul.title-area + li.name= link_to application_name, main_app.root_path + li.toggle-topbar.menu-icon: a href="#": span Menu + .top-bar-section= render 'layouts/navigation_links' diff --git a/spec/dummy/app/views/layouts/_navigation_links.html.slim b/spec/dummy/app/views/layouts/_navigation_links.html.slim new file mode 100644 index 0000000..5a91447 --- /dev/null +++ b/spec/dummy/app/views/layouts/_navigation_links.html.slim @@ -0,0 +1,39 @@ +- if signed_in? + ul.right + li class=active_class('dunlop#changelog') + = link_to Rails.application.config.git_version, dunlop.changelog_path, title: 'Current version, click for changelog' + li class=active_class('dunlop/users#profile', 'dunlop/users#edit_profile') = link_to current_user.email.to_s.sub(/\@.*/, ''), dunlop.profile_users_path + li= link_to 'Sign out', main_app.destroy_user_session_path, method: :delete + ul.left + - if can? :index, WorkflowInstance + li.has-dropdown class=active_class('workflow_instance') + = link_to WorkflowInstance.model_name.human_plural, '#' + ul.dropdown + - WorkflowInstance.scenario_classes.each do |scenario| + - if can? :read, scenario + li class=active_class("workflow_instance/#{scenario.process_name.pluralize}") = link_to scenario.model_name.human_plural, [main_app, scenario] + - if can? :index, WorkflowInstanceBatch + li.has-dropdown class=active_class('workflow_instance_batch') + = link_to WorkflowInstanceBatch.model_name.human_plural, '#' + ul.dropdown + - WorkflowInstance.scenario_classes.each do |scenario| + - if can? :read, scenario.batch_class + li class=active_class("workflow_instance_batch/#{scenario.batch_class.process_name.pluralize}") = link_to scenario.batch_class.model_name.human_plural, [main_app, scenario.batch_class] + /- if can? :index, SourceFile or can? :index, TargetFile + li.has-dropdown class=active_class('dunlop/source_files', 'dunlop/target_files') + = link_to 'Files', '#' + ul.dropdown + - if can? :index, SourceFile + li class=active_class('dunlop/source_files') = link_to SourceFile.model_name.human_plural, dunlop.source_files_path + - if can? :index, TargetFile + li class=active_class('dunlop/target_files') = link_to TargetFile.model_name.human_plural, dunlop.target_files_path + - if can? :index, User + li.has-dropdown class=active_class("dunlop/users", except: /profile$/) + = link_to 'Admin', '#' + ul.dropdown + li class=active_class('dunlop/users', except: /profile$/) = link_to User.model_name.human_plural, dunlop.users_path + /li{ class: active_class('manual') }= link_to 'Manual', manual_root_path +- else + ul.right + li= link_to 'Sign In', main_app.new_user_session_path + diff --git a/spec/dummy/app/views/layouts/application.html.slim b/spec/dummy/app/views/layouts/application.html.slim new file mode 100644 index 0000000..c9ab11f --- /dev/null +++ b/spec/dummy/app/views/layouts/application.html.slim @@ -0,0 +1,27 @@ +doctype html +html + head + meta name="viewport" content="width=device-width, initial-scale=1.0" + title= content_for?(:title) ? yield(:title) : application_name + meta name="description" content="#{content_for?(:description) ? yield(:description) : 'Migration Dashboard'}" + = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true + = javascript_include_tag 'vendor/modernizr' + = javascript_include_tag 'application', 'data-turbolinks-track' => true + = csrf_meta_tags + body class=body_classes + #workflow-step-modal.reveal-modal data-reveal="" + .content + a.close-reveal-modal × + header= render 'layouts/navigation' + main role="main" + .environment-ribbon class=Rails.env + span= Rails.env + = render 'layouts/messages' + = yield + footer + .right + Powered by + = link_to 'FourStack B.V.', 'http://fourstack.nl/', target: :_blank + #display-badge-info-popup.reveal-modal data-reveal="" + .display-badge-info-content + a.close-reveal-modal x diff --git a/spec/dummy/app/views/layouts/mailer.html.erb b/spec/dummy/app/views/layouts/mailer.html.erb new file mode 100644 index 0000000..cbd34d2 --- /dev/null +++ b/spec/dummy/app/views/layouts/mailer.html.erb @@ -0,0 +1,13 @@ + + + + + + + + + <%= yield %> + + diff --git a/spec/dummy/app/views/layouts/mailer.text.erb b/spec/dummy/app/views/layouts/mailer.text.erb new file mode 100644 index 0000000..37f0bdd --- /dev/null +++ b/spec/dummy/app/views/layouts/mailer.text.erb @@ -0,0 +1 @@ +<%= yield %> diff --git a/spec/dummy/app/views/posts/_form.html.slim b/spec/dummy/app/views/posts/_form.html.slim new file mode 100644 index 0000000..733669e --- /dev/null +++ b/spec/dummy/app/views/posts/_form.html.slim @@ -0,0 +1,15 @@ += form_for @post do |f| + - if @post.errors.any? + #error_explanation + h2 = "#{pluralize(@post.errors.count, "error")} prohibited this post from being saved:" + ul + - @post.errors.full_messages.each do |message| + li = message + + .field + = f.label :title + = f.text_field :title + .field + = f.label :body + = f.text_area :body + .actions = f.submit diff --git a/spec/dummy/app/views/posts/edit.html.slim b/spec/dummy/app/views/posts/edit.html.slim new file mode 100644 index 0000000..745d8cc --- /dev/null +++ b/spec/dummy/app/views/posts/edit.html.slim @@ -0,0 +1,8 @@ +h1 Editing post + +== render 'form' + += link_to 'Show', @post +' | += link_to 'Back', posts_path + diff --git a/spec/dummy/app/views/posts/index.html.slim b/spec/dummy/app/views/posts/index.html.slim new file mode 100644 index 0000000..dcc6f20 --- /dev/null +++ b/spec/dummy/app/views/posts/index.html.slim @@ -0,0 +1,23 @@ +h1 Listing posts + +table + thead + tr + th Title + th Body + th + th + th + + tbody + - @posts.each do |post| + tr + td = post.title + td = post.body + td = link_to 'Show', post + td = link_to 'Edit', edit_post_path(post) + td = link_to 'Destroy', post, data: { confirm: 'Are you sure?' }, method: :delete + +br + += link_to 'New Post', new_post_path diff --git a/spec/dummy/app/views/posts/new.html.slim b/spec/dummy/app/views/posts/new.html.slim new file mode 100644 index 0000000..eb7c43f --- /dev/null +++ b/spec/dummy/app/views/posts/new.html.slim @@ -0,0 +1,5 @@ +h1 New post + +== render 'form' + += link_to 'Back', posts_path diff --git a/spec/dummy/app/views/posts/show.html.slim b/spec/dummy/app/views/posts/show.html.slim new file mode 100644 index 0000000..868a1f8 --- /dev/null +++ b/spec/dummy/app/views/posts/show.html.slim @@ -0,0 +1,12 @@ +p#notice = notice + +p + strong Title: + = @post.title +p + strong Body: + = @post.body + += link_to 'Edit', edit_post_path(@post) +' | += link_to 'Back', posts_path diff --git a/spec/dummy/bin/bundle b/spec/dummy/bin/bundle new file mode 100755 index 0000000..66e9889 --- /dev/null +++ b/spec/dummy/bin/bundle @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +load Gem.bin_path('bundler', 'bundle') diff --git a/spec/dummy/bin/rails b/spec/dummy/bin/rails new file mode 100755 index 0000000..0739660 --- /dev/null +++ b/spec/dummy/bin/rails @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +APP_PATH = File.expand_path('../config/application', __dir__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/spec/dummy/bin/rake b/spec/dummy/bin/rake new file mode 100755 index 0000000..1724048 --- /dev/null +++ b/spec/dummy/bin/rake @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/spec/dummy/bin/setup b/spec/dummy/bin/setup new file mode 100755 index 0000000..e620b4d --- /dev/null +++ b/spec/dummy/bin/setup @@ -0,0 +1,34 @@ +#!/usr/bin/env ruby +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a starting point to setup your application. + # Add necessary setup steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # puts "\n== Copying sample files ==" + # unless File.exist?('config/database.yml') + # cp 'config/database.yml.sample', 'config/database.yml' + # end + + puts "\n== Preparing database ==" + system! 'bin/rails db:setup' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/spec/dummy/bin/update b/spec/dummy/bin/update new file mode 100755 index 0000000..a8e4462 --- /dev/null +++ b/spec/dummy/bin/update @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a way to update your development environment automatically. + # Add necessary update steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + puts "\n== Updating database ==" + system! 'bin/rails db:migrate' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/spec/dummy/config.ru b/spec/dummy/config.ru new file mode 100644 index 0000000..f7ba0b5 --- /dev/null +++ b/spec/dummy/config.ru @@ -0,0 +1,5 @@ +# This file is used by Rack-based servers to start the application. + +require_relative 'config/environment' + +run Rails.application diff --git a/spec/dummy/config/application.rb b/spec/dummy/config/application.rb new file mode 100644 index 0000000..5b132a5 --- /dev/null +++ b/spec/dummy/config/application.rb @@ -0,0 +1,37 @@ +require_relative 'boot' + +# Pick the frameworks you want: +require "active_record/railtie" +require "action_controller/railtie" +require "action_view/railtie" +require "action_mailer/railtie" +require "active_job/railtie" +require "action_cable/engine" +# require "rails/test_unit/railtie" +require "sprockets/railtie" + +Bundler.require(*Rails.groups) +require "dunlop/ember" + +module Dummy + class Application < Rails::Application + + config.application_name = "Dummy" + + config.git_version = Rails.env + config.git_version = File.read('REVISION').strip if File.exists?('REVISION') + config.git_version = File.read('OFFLINE_REVISION').strip if File.exists?('OFFLINE_REVISION') + config.load_defaults 5.1 + + config.middleware.insert_before 0, Rack::Cors do + allow do + origins '*' + resource '*', headers: :any, methods: [:get, :post, :options, :delete, :put, :patch] + end + end + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + end +end + diff --git a/spec/dummy/config/boot.rb b/spec/dummy/config/boot.rb new file mode 100644 index 0000000..c9aef85 --- /dev/null +++ b/spec/dummy/config/boot.rb @@ -0,0 +1,5 @@ +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__) + +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) +$LOAD_PATH.unshift File.expand_path('../../../lib', __dir__) diff --git a/spec/dummy/config/cable.yml b/spec/dummy/config/cable.yml new file mode 100644 index 0000000..0bbde6f --- /dev/null +++ b/spec/dummy/config/cable.yml @@ -0,0 +1,9 @@ +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: redis://localhost:6379/1 diff --git a/spec/dummy/config/database.yml b/spec/dummy/config/database.yml new file mode 100644 index 0000000..1c1a37c --- /dev/null +++ b/spec/dummy/config/database.yml @@ -0,0 +1,25 @@ +# SQLite version 3.x +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem 'sqlite3' +# +default: &default + adapter: sqlite3 + pool: 5 + timeout: 5000 + +development: + <<: *default + database: db/development.sqlite3 + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + <<: *default + database: db/test.sqlite3 + +production: + <<: *default + database: db/production.sqlite3 diff --git a/spec/dummy/config/environment.rb b/spec/dummy/config/environment.rb new file mode 100644 index 0000000..426333b --- /dev/null +++ b/spec/dummy/config/environment.rb @@ -0,0 +1,5 @@ +# Load the Rails application. +require_relative 'application' + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/spec/dummy/config/environments/development.rb b/spec/dummy/config/environments/development.rb new file mode 100644 index 0000000..a29bb0e --- /dev/null +++ b/spec/dummy/config/environments/development.rb @@ -0,0 +1,58 @@ +Rails.application.configure do + + config.time_zone = 'Moscow' + config.git_version = 'develop' + + # Settings specified here will take precedence over those in config/application.rb. + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports. + config.consider_all_requests_local = true + + # Enable/disable caching. By default caching is disabled. + if Rails.root.join('tmp/caching-dev.txt').exist? + config.action_controller.perform_caching = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + 'Cache-Control' => 'public, max-age=172800' + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + config.action_mailer.perform_caching = false + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Raise an error on page load if there are pending migrations. + config.active_record.migration_error = :page_load + + # Debug mode disables concatenation and preprocessing of assets. + # This option may cause significant delays in view rendering with a large + # number of complex assets. + config.assets.debug = true + + # Suppress logger output for asset requests. + config.assets.quiet = true + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true + + # Use an evented file watcher to asynchronously detect changes in source code, + # routes, locales, etc. This feature depends on the listen gem. + # config.file_watcher = ActiveSupport::EventedFileUpdateChecker +end diff --git a/spec/dummy/config/environments/production.rb b/spec/dummy/config/environments/production.rb new file mode 100644 index 0000000..739e81c --- /dev/null +++ b/spec/dummy/config/environments/production.rb @@ -0,0 +1,86 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.cache_classes = true + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? + + # Compress JavaScripts and CSS. + config.assets.js_compressor = :uglifier + # config.assets.css_compressor = :sass + + # Do not fallback to assets pipeline if a precompiled asset is missed. + config.assets.compile = false + + # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = 'http://assets.example.com' + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + + # Mount Action Cable outside main process or domain + # config.action_cable.mount_path = nil + # config.action_cable.url = 'wss://example.com/cable' + # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # Use the lowest log level to ensure availability of diagnostic information + # when problems arise. + config.log_level = :debug + + # Prepend all log lines with the following tags. + config.log_tags = [ :request_id ] + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Use a real queuing backend for Active Job (and separate queues per environment) + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "dummy_#{Rails.env}" + config.action_mailer.perform_caching = false + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners. + config.active_support.deprecation = :notify + + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new + + # Use a different logger for distributed setups. + # require 'syslog/logger' + # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') + + if ENV["RAILS_LOG_TO_STDOUT"].present? + logger = ActiveSupport::Logger.new(STDOUT) + logger.formatter = config.log_formatter + config.logger = ActiveSupport::TaggedLogging.new(logger) + end + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false +end diff --git a/spec/dummy/config/environments/test.rb b/spec/dummy/config/environments/test.rb new file mode 100644 index 0000000..8058284 --- /dev/null +++ b/spec/dummy/config/environments/test.rb @@ -0,0 +1,46 @@ +Rails.application.configure do + + config.time_zone = 'Moscow' + config.git_version = 'test' + + # Settings specified here will take precedence over those in config/application.rb. + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Do not eager load code on boot. This avoids loading your whole application + # just for the purpose of running a single test. If you are using a tool that + # preloads Rails for running tests, you may have to set it to true. + config.eager_load = false + + # Configure public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + 'Cache-Control' => 'public, max-age=3600' + } + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates. + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment. + config.action_controller.allow_forgery_protection = false + config.action_mailer.perform_caching = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Print deprecation notices to the stderr. + config.active_support.deprecation = :stderr + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true +end diff --git a/spec/dummy/config/initializers/application_controller_renderer.rb b/spec/dummy/config/initializers/application_controller_renderer.rb new file mode 100644 index 0000000..51639b6 --- /dev/null +++ b/spec/dummy/config/initializers/application_controller_renderer.rb @@ -0,0 +1,6 @@ +# Be sure to restart your server when you modify this file. + +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) diff --git a/spec/dummy/config/initializers/assets.rb b/spec/dummy/config/initializers/assets.rb new file mode 100644 index 0000000..01ef3e6 --- /dev/null +++ b/spec/dummy/config/initializers/assets.rb @@ -0,0 +1,11 @@ +# Be sure to restart your server when you modify this file. + +# Version of your assets, change this if you want to expire all your assets. +Rails.application.config.assets.version = '1.0' + +# Add additional assets to the asset load path +# Rails.application.config.assets.paths << Emoji.images_path + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in app/assets folder are already added. +# Rails.application.config.assets.precompile += %w( search.js ) diff --git a/spec/dummy/config/initializers/backtrace_silencers.rb b/spec/dummy/config/initializers/backtrace_silencers.rb new file mode 100644 index 0000000..59385cd --- /dev/null +++ b/spec/dummy/config/initializers/backtrace_silencers.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/spec/dummy/config/initializers/cookies_serializer.rb b/spec/dummy/config/initializers/cookies_serializer.rb new file mode 100644 index 0000000..5a6a32d --- /dev/null +++ b/spec/dummy/config/initializers/cookies_serializer.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Specify a serializer for the signed and encrypted cookie jars. +# Valid options are :json, :marshal, and :hybrid. +Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/spec/dummy/config/initializers/devise.rb b/spec/dummy/config/initializers/devise.rb new file mode 100644 index 0000000..d52d2c6 --- /dev/null +++ b/spec/dummy/config/initializers/devise.rb @@ -0,0 +1,277 @@ +# Use this hook to configure devise mailer, warden hooks and so forth. +# Many of these configuration options can be set straight in your model. +Devise.setup do |config| + # The secret key used by Devise. Devise uses this key to generate + # random tokens. Changing this key will render invalid all existing + # confirmation, reset password and unlock tokens in the database. + # Devise will use the `secret_key_base` as its `secret_key` + # by default. You can change it below and use your own secret key. + config.secret_key = '3538d800ea7a5fe1dba29d51c998fc44ee9728cb1d88ab536549e8a4d1ed224dc49ba6675d7a31e2fe3fe4fcd4ec677411c673ad862b2e853f1cf3ad0c31ee7f' + + # ==> Mailer Configuration + # Configure the e-mail address which will be shown in Devise::Mailer, + # note that it will be overwritten if you use your own mailer class + # with default "from" parameter. + config.mailer_sender = 'dummy-test@example.com' + + # Configure the class responsible to send e-mails. + # config.mailer = 'Devise::Mailer' + + # Configure the parent class responsible to send e-mails. + # config.parent_mailer = 'ActionMailer::Base' + + # ==> ORM configuration + # Load and configure the ORM. Supports :active_record (default) and + # :mongoid (bson_ext recommended) by default. Other ORMs may be + # available as additional gems. + require 'devise/orm/active_record' + + # ==> Configuration for any authentication mechanism + # Configure which keys are used when authenticating a user. The default is + # just :email. You can configure it to use [:username, :subdomain], so for + # authenticating a user, both parameters are required. Remember that those + # parameters are used only when authenticating and not when retrieving from + # session. If you need permissions, you should implement that in a before filter. + # You can also supply a hash where the value is a boolean determining whether + # or not authentication should be aborted when the value is not present. + # config.authentication_keys = [:email] + + # Configure parameters from the request object used for authentication. Each entry + # given should be a request method and it will automatically be passed to the + # find_for_authentication method and considered in your model lookup. For instance, + # if you set :request_keys to [:subdomain], :subdomain will be used on authentication. + # The same considerations mentioned for authentication_keys also apply to request_keys. + # config.request_keys = [] + + # Configure which authentication keys should be case-insensitive. + # These keys will be downcased upon creating or modifying a user and when used + # to authenticate or find a user. Default is :email. + config.case_insensitive_keys = [:email] + + # Configure which authentication keys should have whitespace stripped. + # These keys will have whitespace before and after removed upon creating or + # modifying a user and when used to authenticate or find a user. Default is :email. + config.strip_whitespace_keys = [:email] + + # Tell if authentication through request.params is enabled. True by default. + # It can be set to an array that will enable params authentication only for the + # given strategies, for example, `config.params_authenticatable = [:database]` will + # enable it only for database (email + password) authentication. + # config.params_authenticatable = true + + # Tell if authentication through HTTP Auth is enabled. False by default. + # It can be set to an array that will enable http authentication only for the + # given strategies, for example, `config.http_authenticatable = [:database]` will + # enable it only for database authentication. The supported strategies are: + # :database = Support basic authentication with authentication key + password + # config.http_authenticatable = false + + # If 401 status code should be returned for AJAX requests. True by default. + # config.http_authenticatable_on_xhr = true + + # The realm used in Http Basic Authentication. 'Application' by default. + # config.http_authentication_realm = 'Application' + + # It will change confirmation, password recovery and other workflows + # to behave the same regardless if the e-mail provided was right or wrong. + # Does not affect registerable. + # config.paranoid = true + + # By default Devise will store the user in session. You can skip storage for + # particular strategies by setting this option. + # Notice that if you are skipping storage for all authentication paths, you + # may want to disable generating routes to Devise's sessions controller by + # passing skip: :sessions to `devise_for` in your config/routes.rb + config.skip_session_storage = [:http_auth] + + # By default, Devise cleans up the CSRF token on authentication to + # avoid CSRF token fixation attacks. This means that, when using AJAX + # requests for sign in and sign up, you need to get a new CSRF token + # from the server. You can disable this option at your own risk. + # config.clean_up_csrf_token_on_authentication = true + + # When false, Devise will not attempt to reload routes on eager load. + # This can reduce the time taken to boot the app but if your application + # requires the Devise mappings to be loaded during boot time the application + # won't boot properly. + # config.reload_routes = true + + # ==> Configuration for :database_authenticatable + # For bcrypt, this is the cost for hashing the password and defaults to 11. If + # using other algorithms, it sets how many times you want the password to be hashed. + # + # Limiting the stretches to just one in testing will increase the performance of + # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use + # a value less than 10 in other environments. Note that, for bcrypt (the default + # algorithm), the cost increases exponentially with the number of stretches (e.g. + # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation). + config.stretches = Rails.env.test? ? 1 : 11 + + # Set up a pepper to generate the hashed password. + # config.pepper = '49df74b77985daa55af0cbbaa610e93dbffd32d2d3c211e9a2f46c8fc0b8555359077fce9803b8ed7e9dae4a7e5d6d728b94c23a0e2c654b29da2b1c901cff80' + + # Send a notification to the original email when the user's email is changed. + # config.send_email_changed_notification = false + + # Send a notification email when the user's password is changed. + # config.send_password_change_notification = false + + # ==> Configuration for :confirmable + # A period that the user is allowed to access the website even without + # confirming their account. For instance, if set to 2.days, the user will be + # able to access the website for two days without confirming their account, + # access will be blocked just in the third day. Default is 0.days, meaning + # the user cannot access the website without confirming their account. + # config.allow_unconfirmed_access_for = 2.days + + # A period that the user is allowed to confirm their account before their + # token becomes invalid. For example, if set to 3.days, the user can confirm + # their account within 3 days after the mail was sent, but on the fourth day + # their account can't be confirmed with the token any more. + # Default is nil, meaning there is no restriction on how long a user can take + # before confirming their account. + # config.confirm_within = 3.days + + # If true, requires any email changes to be confirmed (exactly the same way as + # initial account confirmation) to be applied. Requires additional unconfirmed_email + # db field (see migrations). Until confirmed, new email is stored in + # unconfirmed_email column, and copied to email column on successful confirmation. + config.reconfirmable = true + + # Defines which key will be used when confirming an account + # config.confirmation_keys = [:email] + + # ==> Configuration for :rememberable + # The time the user will be remembered without asking for credentials again. + # config.remember_for = 2.weeks + + # Invalidates all the remember me tokens when the user signs out. + config.expire_all_remember_me_on_sign_out = true + + # If true, extends the user's remember period when remembered via cookie. + # config.extend_remember_period = false + + # Options to be passed to the created cookie. For instance, you can set + # secure: true in order to force SSL only cookies. + # config.rememberable_options = {} + + # ==> Configuration for :validatable + # Range for password length. + config.password_length = 6..128 + + # Email regex used to validate email formats. It simply asserts that + # one (and only one) @ exists in the given string. This is mainly + # to give user feedback and not to assert the e-mail validity. + config.email_regexp = /\A[^@\s]+@[^@\s]+\z/ + + # ==> Configuration for :timeoutable + # The time you want to timeout the user session without activity. After this + # time the user will be asked for credentials again. Default is 30 minutes. + # config.timeout_in = 30.minutes + + # ==> Configuration for :lockable + # Defines which strategy will be used to lock an account. + # :failed_attempts = Locks an account after a number of failed attempts to sign in. + # :none = No lock strategy. You should handle locking by yourself. + # config.lock_strategy = :failed_attempts + + # Defines which key will be used when locking and unlocking an account + # config.unlock_keys = [:email] + + # Defines which strategy will be used to unlock an account. + # :email = Sends an unlock link to the user email + # :time = Re-enables login after a certain amount of time (see :unlock_in below) + # :both = Enables both strategies + # :none = No unlock strategy. You should handle unlocking by yourself. + # config.unlock_strategy = :both + + # Number of authentication tries before locking an account if lock_strategy + # is failed attempts. + # config.maximum_attempts = 20 + + # Time interval to unlock the account if :time is enabled as unlock_strategy. + # config.unlock_in = 1.hour + + # Warn on the last attempt before the account is locked. + # config.last_attempt_warning = true + + # ==> Configuration for :recoverable + # + # Defines which key will be used when recovering the password for an account + # config.reset_password_keys = [:email] + + # Time interval you can reset your password with a reset password key. + # Don't put a too small interval or your users won't have the time to + # change their passwords. + config.reset_password_within = 6.hours + + # When set to false, does not sign a user in automatically after their password is + # reset. Defaults to true, so a user is signed in automatically after a reset. + # config.sign_in_after_reset_password = true + + # ==> Configuration for :encryptable + # Allow you to use another hashing or encryption algorithm besides bcrypt (default). + # You can use :sha1, :sha512 or algorithms from others authentication tools as + # :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20 + # for default behavior) and :restful_authentication_sha1 (then you should set + # stretches to 10, and copy REST_AUTH_SITE_KEY to pepper). + # + # Require the `devise-encryptable` gem when using anything other than bcrypt + # config.encryptor = :sha512 + + # ==> Scopes configuration + # Turn scoped views on. Before rendering "sessions/new", it will first check for + # "users/sessions/new". It's turned off by default because it's slower if you + # are using only default views. + # config.scoped_views = false + + # Configure the default scope given to Warden. By default it's the first + # devise role declared in your routes (usually :user). + # config.default_scope = :user + + # Set this configuration to false if you want /users/sign_out to sign out + # only the current scope. By default, Devise signs out all scopes. + # config.sign_out_all_scopes = true + + # ==> Navigation configuration + # Lists the formats that should be treated as navigational. Formats like + # :html, should redirect to the sign in page when the user does not have + # access, but formats like :xml or :json, should return 401. + # + # If you have any extra navigational formats, like :iphone or :mobile, you + # should add them to the navigational formats lists. + # + # The "*/*" below is required to match Internet Explorer requests. + # config.navigational_formats = ['*/*', :html] + + # The default HTTP method used to sign out a resource. Default is :delete. + config.sign_out_via = :delete + + # ==> OmniAuth + # Add a new OmniAuth provider. Check the wiki for more information on setting + # up on your models and hooks. + # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo' + + # ==> Warden configuration + # If you want to use other strategies, that are not supported by Devise, or + # change the failure app, you can configure them inside the config.warden block. + # + # config.warden do |manager| + # manager.intercept_401 = false + # manager.default_strategies(scope: :user).unshift :some_external_strategy + # end + + # ==> Mountable engine configurations + # When using Devise inside an engine, let's call it `MyEngine`, and this engine + # is mountable, there are some extra configurations to be taken into account. + # The following options are available, assuming the engine is mounted as: + # + # mount MyEngine, at: '/my_engine' + # + # The router that invoked `devise_for`, in the example above, would be: + # config.router_name = :my_engine + # + # When using OmniAuth, Devise cannot automatically set OmniAuth path, + # so you need to do it manually. For the users scope, it would be: + # config.omniauth_path_prefix = '/my_engine/users/auth' +end diff --git a/spec/dummy/config/initializers/filter_parameter_logging.rb b/spec/dummy/config/initializers/filter_parameter_logging.rb new file mode 100644 index 0000000..4a994e1 --- /dev/null +++ b/spec/dummy/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Configure sensitive parameters which will be filtered from the log file. +Rails.application.config.filter_parameters += [:password] diff --git a/spec/dummy/config/initializers/inflections.rb b/spec/dummy/config/initializers/inflections.rb new file mode 100644 index 0000000..ac033bf --- /dev/null +++ b/spec/dummy/config/initializers/inflections.rb @@ -0,0 +1,16 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.plural /^(ox)$/i, '\1en' +# inflect.singular /^(ox)en/i, '\1' +# inflect.irregular 'person', 'people' +# inflect.uncountable %w( fish sheep ) +# end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym 'RESTful' +# end diff --git a/spec/dummy/config/initializers/mime_types.rb b/spec/dummy/config/initializers/mime_types.rb new file mode 100644 index 0000000..dc18996 --- /dev/null +++ b/spec/dummy/config/initializers/mime_types.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf diff --git a/spec/dummy/config/initializers/new_framework_defaults.rb b/spec/dummy/config/initializers/new_framework_defaults.rb new file mode 100644 index 0000000..671abb6 --- /dev/null +++ b/spec/dummy/config/initializers/new_framework_defaults.rb @@ -0,0 +1,24 @@ +# Be sure to restart your server when you modify this file. +# +# This file contains migration options to ease your Rails 5.0 upgrade. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. + +# Enable per-form CSRF tokens. Previous versions had false. +Rails.application.config.action_controller.per_form_csrf_tokens = true + +# Enable origin-checking CSRF mitigation. Previous versions had false. +Rails.application.config.action_controller.forgery_protection_origin_check = true + +# Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`. +# Previous versions had false. +ActiveSupport.to_time_preserves_timezone = true + +# Require `belongs_to` associations by default. Previous versions had false. +Rails.application.config.active_record.belongs_to_required_by_default = true + +# Do not halt callback chains when a callback returns false. Previous versions had true. +ActiveSupport.halt_callback_chains_on_return_false = false + +# Configure SSL options to enable HSTS with subdomains. Previous versions had false. +Rails.application.config.ssl_options = { hsts: { subdomains: true } } diff --git a/spec/dummy/config/initializers/session_store.rb b/spec/dummy/config/initializers/session_store.rb new file mode 100644 index 0000000..e766b67 --- /dev/null +++ b/spec/dummy/config/initializers/session_store.rb @@ -0,0 +1,3 @@ +# Be sure to restart your server when you modify this file. + +Rails.application.config.session_store :cookie_store, key: '_dummy_session' diff --git a/spec/dummy/config/initializers/wrap_parameters.rb b/spec/dummy/config/initializers/wrap_parameters.rb new file mode 100644 index 0000000..bbfc396 --- /dev/null +++ b/spec/dummy/config/initializers/wrap_parameters.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. + +# This file contains settings for ActionController::ParamsWrapper which +# is enabled by default. + +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +ActiveSupport.on_load(:action_controller) do + wrap_parameters format: [:json] +end + +# To enable root element in JSON for ActiveRecord objects. +# ActiveSupport.on_load(:active_record) do +# self.include_root_in_json = true +# end diff --git a/spec/dummy/config/locales/devise.en.yml b/spec/dummy/config/locales/devise.en.yml new file mode 100644 index 0000000..0b8f130 --- /dev/null +++ b/spec/dummy/config/locales/devise.en.yml @@ -0,0 +1,64 @@ +# Additional translations at https://github.com/plataformatec/devise/wiki/I18n + +en: + devise: + confirmations: + confirmed: "Your email address has been successfully confirmed." + send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes." + send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes." + failure: + already_authenticated: "You are already signed in." + inactive: "Your account is not activated yet." + invalid: "Invalid %{authentication_keys} or password." + locked: "Your account is locked." + last_attempt: "You have one more attempt before your account is locked." + not_found_in_database: "Invalid %{authentication_keys} or password." + timeout: "Your session expired. Please sign in again to continue." + unauthenticated: "You need to sign in or sign up before continuing." + unconfirmed: "You have to confirm your email address before continuing." + mailer: + confirmation_instructions: + subject: "Confirmation instructions" + reset_password_instructions: + subject: "Reset password instructions" + unlock_instructions: + subject: "Unlock instructions" + email_changed: + subject: "Email Changed" + password_change: + subject: "Password Changed" + omniauth_callbacks: + failure: "Could not authenticate you from %{kind} because \"%{reason}\"." + success: "Successfully authenticated from %{kind} account." + passwords: + no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided." + send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes." + send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes." + updated: "Your password has been changed successfully. You are now signed in." + updated_not_active: "Your password has been changed successfully." + registrations: + destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon." + signed_up: "Welcome! You have signed up successfully." + signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated." + signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked." + signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account." + update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address." + updated: "Your account has been updated successfully." + sessions: + signed_in: "Signed in successfully." + signed_out: "Signed out successfully." + already_signed_out: "Signed out successfully." + unlocks: + send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes." + send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes." + unlocked: "Your account has been unlocked successfully. Please sign in to continue." + errors: + messages: + already_confirmed: "was already confirmed, please try signing in" + confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one" + expired: "has expired, please request a new one" + not_found: "not found" + not_locked: "was not locked" + not_saved: + one: "1 error prohibited this %{resource} from being saved:" + other: "%{count} errors prohibited this %{resource} from being saved:" diff --git a/spec/dummy/config/locales/en.yml b/spec/dummy/config/locales/en.yml new file mode 100644 index 0000000..0653957 --- /dev/null +++ b/spec/dummy/config/locales/en.yml @@ -0,0 +1,23 @@ +# Files in the config/locales directory are used for internationalization +# and are automatically loaded by Rails. If you want to use locales other +# than English, add the necessary files in this directory. +# +# To use the locales, use `I18n.t`: +# +# I18n.t 'hello' +# +# In views, this is aliased to just `t`: +# +# <%= t('hello') %> +# +# To use a different locale, set it with `I18n.locale`: +# +# I18n.locale = :es +# +# This would use the information in config/locales/es.yml. +# +# To learn more, please read the Rails Internationalization guide +# available at http://guides.rubyonrails.org/i18n.html. + +en: + hello: "Hello world" diff --git a/spec/dummy/config/puma.rb b/spec/dummy/config/puma.rb new file mode 100644 index 0000000..c7f311f --- /dev/null +++ b/spec/dummy/config/puma.rb @@ -0,0 +1,47 @@ +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum, this matches the default thread size of Active Record. +# +threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i +threads threads_count, threads_count + +# Specifies the `port` that Puma will listen on to receive requests, default is 3000. +# +port ENV.fetch("PORT") { 3000 } + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked webserver processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. If you use this option +# you need to make sure to reconnect any threads in the `on_worker_boot` +# block. +# +# preload_app! + +# The code in the `on_worker_boot` will be called if you are using +# clustered mode by specifying a number of `workers`. After each worker +# process is booted this block will be run, if you are using `preload_app!` +# option you will want to use this block to reconnect to any threads +# or connections that may have been created at application boot, Ruby +# cannot share connections between processes. +# +# on_worker_boot do +# ActiveRecord::Base.establish_connection if defined?(ActiveRecord) +# end + +# Allow puma to be restarted by `rails restart` command. +plugin :tmp_restart diff --git a/spec/dummy/config/routes.rb b/spec/dummy/config/routes.rb new file mode 100644 index 0000000..bd291d2 --- /dev/null +++ b/spec/dummy/config/routes.rb @@ -0,0 +1,11 @@ +Rails.application.routes.draw do + mount Dunlop::Engine => "/dunlop" + resources :comments + resources :posts + devise_for :users + mount Dunlop::Ember::Engine => "/app", as: :app + namespace :api do + resources :comments + resources :posts + end +end diff --git a/spec/dummy/config/secrets.yml b/spec/dummy/config/secrets.yml new file mode 100644 index 0000000..166b869 --- /dev/null +++ b/spec/dummy/config/secrets.yml @@ -0,0 +1,22 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key is used for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! + +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +# You can use `rails secret` to generate a secure secret key. + +# Make sure the secrets in this file are kept private +# if you're sharing your code publicly. + +development: + secret_key_base: 0c559e89f99778575a9fac1cb44f0aefedeac486b1c7c1614a9f5c1467acca856b7bae0ca89b1c6975f81857619dcdd04f2947e0b07a759f67503450f46046da + +test: + secret_key_base: 6ea9df1b658a31fd40e3caf40733753351964092ceddcb573c7515a33606c8d795166fa3c4df1bf89eb74a8383ad9eb6278498719b8806ab72e9816ca69f0dc3 + +# Do not keep production secrets in the repository, +# instead read values from the environment. +production: + secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> diff --git a/spec/dummy/config/spring.rb b/spec/dummy/config/spring.rb new file mode 100644 index 0000000..c9119b4 --- /dev/null +++ b/spec/dummy/config/spring.rb @@ -0,0 +1,6 @@ +%w( + .ruby-version + .rbenv-vars + tmp/restart.txt + tmp/caching-dev.txt +).each { |path| Spring.watch(path) } diff --git a/spec/dummy/db/migrate/20170926045124_create_posts.rb b/spec/dummy/db/migrate/20170926045124_create_posts.rb new file mode 100644 index 0000000..b788575 --- /dev/null +++ b/spec/dummy/db/migrate/20170926045124_create_posts.rb @@ -0,0 +1,10 @@ +class CreatePosts < ActiveRecord::Migration[5.1] + def change + create_table :posts do |t| + t.string :title + t.text :body + + t.timestamps + end + end +end diff --git a/spec/dummy/db/migrate/20170926045157_create_comments.rb b/spec/dummy/db/migrate/20170926045157_create_comments.rb new file mode 100644 index 0000000..4ac277e --- /dev/null +++ b/spec/dummy/db/migrate/20170926045157_create_comments.rb @@ -0,0 +1,11 @@ +class CreateComments < ActiveRecord::Migration[5.1] + def change + create_table :comments do |t| + t.integer :user_id + t.integer :post_id + t.text :body + + t.timestamps + end + end +end diff --git a/spec/dummy/db/migrate/20170926045305_devise_create_users.rb b/spec/dummy/db/migrate/20170926045305_devise_create_users.rb new file mode 100644 index 0000000..060217e --- /dev/null +++ b/spec/dummy/db/migrate/20170926045305_devise_create_users.rb @@ -0,0 +1,42 @@ +class DeviseCreateUsers < ActiveRecord::Migration[5.1] + def change + create_table :users do |t| + ## Database authenticatable + t.string :email, null: false, default: "" + t.string :encrypted_password, null: false, default: "" + + ## Recoverable + t.string :reset_password_token + t.datetime :reset_password_sent_at + + ## Rememberable + t.datetime :remember_created_at + + ## Trackable + t.integer :sign_in_count, default: 0, null: false + t.datetime :current_sign_in_at + t.datetime :last_sign_in_at + t.string :current_sign_in_ip + t.string :last_sign_in_ip + + ## Confirmable + # t.string :confirmation_token + # t.datetime :confirmed_at + # t.datetime :confirmation_sent_at + # t.string :unconfirmed_email # Only if using reconfirmable + + ## Lockable + # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts + # t.string :unlock_token # Only if unlock strategy is :email or :both + # t.datetime :locked_at + + + t.timestamps null: false + end + + add_index :users, :email, unique: true + add_index :users, :reset_password_token, unique: true + # add_index :users, :confirmation_token, unique: true + # add_index :users, :unlock_token, unique: true + end +end diff --git a/spec/dummy/db/migrate/20170926050413_add_admin_and_role_names_to_users.rb b/spec/dummy/db/migrate/20170926050413_add_admin_and_role_names_to_users.rb new file mode 100644 index 0000000..fc5116d --- /dev/null +++ b/spec/dummy/db/migrate/20170926050413_add_admin_and_role_names_to_users.rb @@ -0,0 +1,9 @@ +class AddAdminAndRoleNamesToUsers < ActiveRecord::Migration[5.1] + def change + add_column :users, :admin, :boolean, default: false, null: false + add_column :users, :role_names, :text + add_column :users, :role_names_admin, :text + add_column :users, :settings_storage, :text + end +end + diff --git a/spec/dummy/db/schema.rb b/spec/dummy/db/schema.rb new file mode 100644 index 0000000..a447bb3 --- /dev/null +++ b/spec/dummy/db/schema.rb @@ -0,0 +1,51 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema.define(version: 20170926050413) do + + create_table "comments", force: :cascade do |t| + t.integer "user_id" + t.integer "post_id" + t.text "body" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "posts", force: :cascade do |t| + t.string "title" + t.text "body" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "users", force: :cascade do |t| + t.string "email", default: "", null: false + t.string "encrypted_password", default: "", null: false + t.string "reset_password_token" + t.datetime "reset_password_sent_at" + t.datetime "remember_created_at" + t.integer "sign_in_count", default: 0, null: false + t.datetime "current_sign_in_at" + t.datetime "last_sign_in_at" + t.string "current_sign_in_ip" + t.string "last_sign_in_ip" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "admin", default: false, null: false + t.text "role_names" + t.text "role_names_admin" + t.text "settings_storage" + t.index ["email"], name: "index_users_on_email", unique: true + t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true + end + +end diff --git a/spec/dummy/lib/assets/.keep b/spec/dummy/lib/assets/.keep new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/log/.keep b/spec/dummy/log/.keep new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/public/404.html b/spec/dummy/public/404.html new file mode 100644 index 0000000..b612547 --- /dev/null +++ b/spec/dummy/public/404.html @@ -0,0 +1,67 @@ + + + + The page you were looking for doesn't exist (404) + + + + + + +
+
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/spec/dummy/public/422.html b/spec/dummy/public/422.html new file mode 100644 index 0000000..a21f82b --- /dev/null +++ b/spec/dummy/public/422.html @@ -0,0 +1,67 @@ + + + + The change you wanted was rejected (422) + + + + + + +
+
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/spec/dummy/public/500.html b/spec/dummy/public/500.html new file mode 100644 index 0000000..061abc5 --- /dev/null +++ b/spec/dummy/public/500.html @@ -0,0 +1,66 @@ + + + + We're sorry, but something went wrong (500) + + + + + + +
+
+

We're sorry, but something went wrong.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/spec/dummy/public/apple-touch-icon-precomposed.png b/spec/dummy/public/apple-touch-icon-precomposed.png new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/public/apple-touch-icon.png b/spec/dummy/public/apple-touch-icon.png new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/public/favicon.ico b/spec/dummy/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/spec/factories/comments.rb b/spec/factories/comments.rb new file mode 100644 index 0000000..9e0265a --- /dev/null +++ b/spec/factories/comments.rb @@ -0,0 +1,7 @@ +FactoryGirl.define do + factory :comment do + user_id 1 + post_id 1 + body "MyText" + end +end diff --git a/spec/factories/posts.rb b/spec/factories/posts.rb new file mode 100644 index 0000000..d905de2 --- /dev/null +++ b/spec/factories/posts.rb @@ -0,0 +1,6 @@ +FactoryGirl.define do + factory :post do + sequence(:title) {|i| "post-#{i}"} + sequence(:body) {|i| "post-body-#{i}"} + end +end diff --git a/spec/factories/users.rb b/spec/factories/users.rb new file mode 100644 index 0000000..152e380 --- /dev/null +++ b/spec/factories/users.rb @@ -0,0 +1,9 @@ +FactoryGirl.define do + factory :user do + sequence(:email) { |i| "user#{i}@example.com" } + password 'secret' + end + factory :admin, parent: :user do + admin true + end +end diff --git a/spec/lib/dunlop/ember/api_base_controller_spec.rb b/spec/lib/dunlop/ember/api_base_controller_spec.rb new file mode 100644 index 0000000..93fd740 --- /dev/null +++ b/spec/lib/dunlop/ember/api_base_controller_spec.rb @@ -0,0 +1,62 @@ +# root application situation +class Test1 +end +module Api + class Test1sController < ApplicationController + include Dunlop::Ember::ApiBaseController + end +end + +# namespaced engine situation +module Adapter1 + class Test2 + end + module Api + class Test2sController < ApplicationController + include Dunlop::Ember::ApiBaseController + end + class RootFallBackModelsController < ApplicationController + include Dunlop::Ember::ApiBaseController + end + end +end + +class RootFallBackModel + # Root model, requested by namespaced controller +end + +describe Dunlop::Ember::ApiBaseController do + describe '#record_class private method, but for now because of unit control' do + it "finds the proper class on Api:: namespace" do + Api::Test1sController.new.record_class.should eq Test1 + end + + it "finds the proper class on Adapter::Api:: namespace" do + Adapter1::Api::Test2sController.new.record_class.should eq Adapter1::Test2 + end + + it 'falls back to demodularized version if namespaced version is not found' do + controller = Adapter1::Api::RootFallBackModelsController.new + controller.record_class.should eq RootFallBackModel + end + end + + describe '#record_params' do + it "finds the proper class on Api:: namespace" do + controller = Api::Test1sController.new + expect(controller).to receive(:params).and_return ActionController::Parameters.new(test1: {a: 1, b: 2}) + expect(controller).to receive(:permitted_params).and_return [:a] + controller.__send__(:record_params).to_hash.should eq('a' => 1) + end + + it "finds the proper class on Adapter::Api:: namespace" do + controller = Adapter1::Api::Test2sController.new + expect(controller).to receive(:params).and_return ActionController::Parameters.new('adapter1/test2' => {a: 1, b: 2}) + expect(controller).to receive(:permitted_params).and_return [:b] + controller.__send__(:record_params).to_hash.should eq('b' => 2) + end + + end +end + + diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb new file mode 100644 index 0000000..10b4c2b --- /dev/null +++ b/spec/rails_helper.rb @@ -0,0 +1,97 @@ +# This file is copied to spec/ when you run 'rails generate rspec:install' +require 'spec_helper' +ENV['RAILS_ENV'] ||= 'test' +test_log = File.expand_path('../dummy/log/test.log', __FILE__) +File.delete(test_log) if File.exist?(test_log) +require File.expand_path("../dummy/config/environment.rb", __FILE__) + +# Prevent database truncation if the environment is production +abort("The Rails environment is running in production mode!") if Rails.env.production? +require 'rspec/rails' +require 'pry' +require 'rspec/rails' +require 'devise' +require 'rspec/dunlop' +#require 'capybara/poltergeist' + +ENGINE_RAILS_ROOT=File.join(File.dirname(__FILE__), '../') +# Requires supporting ruby files with custom matchers and macros, etc, +# in spec/support/ and its subdirectories. +Dir[File.join(ENGINE_RAILS_ROOT, "spec/support/**/*.rb")].each {|f| require f } +Dir[File.join(ENGINE_RAILS_ROOT, "spec/factories/**/*.rb")].each {|f| require f } +#FactoryGirl.definition_file_paths = [File.join(ENGINE_RAILS_ROOT, "spec/factories/**/*.rb")] # not needed here +Dir.glob("spec/acceptance/steps/**/*steps.rb") { |f| load f, true } + +# Add additional requires below this line. Rails is not loaded until this point! + +# Requires supporting ruby files with custom matchers and macros, etc, in +# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are +# run as spec files by default. This means that files in spec/support that end +# in _spec.rb will both be required and run as specs, causing the specs to be +# run twice. It is recommended that you do not name files matching this glob to +# end with _spec.rb. You can configure this pattern with the --pattern +# option on the command line or in ~/.rspec, .rspec or `.rspec-local`. +# +# The following line is provided for convenience purposes. It has the downside +# of increasing the boot-up time by auto-requiring all files in the support +# directory. Alternatively, in the individual `*_spec.rb` files, manually +# require only the support files necessary. +# +# Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } + +# Checks for pending migration and applies them before tests are run. +# If you are not using ActiveRecord, you can remove this line. +ActiveRecord::Migration.maintain_test_schema! +module ControllerJuice + def assert_json(obj) + response.body.should eq obj.to_json + end +end +DatabaseCleaner.strategy = :truncation +RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = 10_000 # do not trash string like: expected: "abc .... def" +RSpec.configure do |config| + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures + config.fixture_path = "#{::Rails.root}/spec/fixtures" + config.expect_with(:rspec) { |c| c.syntax = [:should, :expect] } + config.include FactoryGirl::Syntax::Methods + config.include Rspec::Dunlop::GeneralHelpers + config.include Rspec::Dunlop::FeatureHelpers, type: :feature + config.include Devise::Test::ControllerHelpers, type: :controller + config.include ControllerJuice, type: :controller + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + config.use_transactional_fixtures = false + config.before :suite do + #FactoryGirl.reload # to add the adapter factories + #DatabaseCleaner.clean_with(:truncation) + DatabaseCleaner.clean_with(:truncation) + Dunlop::NestedLogger.options[:yaml_options][:line_width] = 2000 + Warden.test_mode! + end + + config.before :each do + DatabaseCleaner.clean + end + + # RSpec Rails can automatically mix in different behaviours to your tests + # based on their file location, for example enabling you to call `get` and + # `post` in specs under `spec/controllers`. + # + # You can disable this behaviour by removing the line below, and instead + # explicitly tag your specs with their type, e.g.: + # + # RSpec.describe UsersController, :type => :controller do + # # ... + # end + # + # The different available types are documented in the features, such as in + # https://relishapp.com/rspec/rspec-rails/docs + config.infer_spec_type_from_file_location! + + # Filter lines from Rails gems in backtraces. + config.filter_rails_from_backtrace! + # arbitrary gems may also be filtered via: + # config.filter_gems_from_backtrace("gem name") +end diff --git a/spec/routing/app_routing_spec.rb b/spec/routing/app_routing_spec.rb new file mode 100644 index 0000000..2f04849 --- /dev/null +++ b/spec/routing/app_routing_spec.rb @@ -0,0 +1,17 @@ +describe "app routing" do + routes { Dunlop::Ember::Engine.routes } + it 'has a root' do + expect(get: "/").to route_to( + controller: "dunlop/ember/application", + action: "ember_path" + ) + end + + it "works with dashes", type: :routing do + expect(get: "abc-def").to route_to( + controller: "dunlop/ember/application", + action: "ember_path", + rest: 'abc-def' + ) + end +end diff --git a/spec/services/flat_keys_spec.rb b/spec/services/flat_keys_spec.rb new file mode 100644 index 0000000..5c0668c --- /dev/null +++ b/spec/services/flat_keys_spec.rb @@ -0,0 +1,58 @@ +RSpec.describe FlatKeys do + describe '#as_nested_structure' do + it "works" do + result = FlatKeys.as_nested_structure([ + 'root_one', + 'inventories.location.site', + 'ppls.distribution_cables', + 'dslams.port_spec', + 'root_two', + 'dslams.other_spec', + 'root_three', + #'dslams.other_spec.and_then.some', # should raise + 'very.deep.nested.structure.just.because.we.can', + 'very.deep.nested.structure.with.other.tail', + 'start.with.more.than.what.comes.after', + 'start.with.more.than.what.comes', + 'start.with.less.than.what.comes', + 'start.with.less.than.what.comes2.after', + 'start.with.less.than.what.comes.after', + 'start.with.less.than.what.comes2.after', # duplicate, should be no problem + ]) + + expect( result ).to eq [ + :root_one, + :root_two, + :root_three, + { + inventories: {location: :site}, + ppls: :distribution_cables, + dslams: [:port_spec, :other_spec], + very: { + deep: { + nested: { + structure: { + just: { + because: {we: :can} + }, + with: {other: :tail} + } + } + } + }, + start: { + with: { + more: { + than: {what: {comes: :after}} + }, + less: { + than: {what: {comes: :after, comes2: :after}} + } + } + } + } + ] + end + + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..ce33d66 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,96 @@ +# This file was generated by the `rails generate rspec:install` command. Conventionally, all +# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. +# The generated `.rspec` file contains `--require spec_helper` which will cause +# this file to always be loaded, without a need to explicitly require it in any +# files. +# +# Given that it is always loaded, you are encouraged to keep this file as +# light-weight as possible. Requiring heavyweight dependencies from this file +# will add to the boot time of your test suite on EVERY test run, even for an +# individual file that may not need all of that loaded. Instead, consider making +# a separate helper file that requires the additional dependencies and performs +# the additional setup, and require it from the spec files that actually need +# it. +# +# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration +RSpec.configure do |config| + # rspec-expectations config goes here. You can use an alternate + # assertion/expectation library such as wrong or the stdlib/minitest + # assertions if you prefer. + config.expect_with :rspec do |expectations| + # This option will default to `true` in RSpec 4. It makes the `description` + # and `failure_message` of custom matchers include text for helper methods + # defined using `chain`, e.g.: + # be_bigger_than(2).and_smaller_than(4).description + # # => "be bigger than 2 and smaller than 4" + # ...rather than: + # # => "be bigger than 2" + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + # rspec-mocks config goes here. You can use an alternate test double + # library (such as bogus or mocha) by changing the `mock_with` option here. + config.mock_with :rspec do |mocks| + # Prevents you from mocking or stubbing a method that does not exist on + # a real object. This is generally recommended, and will default to + # `true` in RSpec 4. + mocks.verify_partial_doubles = true + end + + # This option will default to `:apply_to_host_groups` in RSpec 4 (and will + # have no way to turn it off -- the option exists only for backwards + # compatibility in RSpec 3). It causes shared context metadata to be + # inherited by the metadata hash of host groups and examples, rather than + # triggering implicit auto-inclusion in groups with matching metadata. + config.shared_context_metadata_behavior = :apply_to_host_groups + +# The settings below are suggested to provide a good initial experience +# with RSpec, but feel free to customize to your heart's content. +=begin + # This allows you to limit a spec run to individual examples or groups + # you care about by tagging them with `:focus` metadata. When nothing + # is tagged with `:focus`, all examples get run. RSpec also provides + # aliases for `it`, `describe`, and `context` that include `:focus` + # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + config.filter_run_when_matching :focus + + # Allows RSpec to persist some state between runs in order to support + # the `--only-failures` and `--next-failure` CLI options. We recommend + # you configure your source control system to ignore this file. + config.example_status_persistence_file_path = "spec/examples.txt" + + # Limits the available syntax to the non-monkey patched syntax that is + # recommended. For more details, see: + # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ + # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode + config.disable_monkey_patching! + + # Many RSpec users commonly either run the entire suite or an individual + # file, and it's useful to allow more verbose output when running an + # individual spec file. + if config.files_to_run.one? + # Use the documentation formatter for detailed output, + # unless a formatter has already been configured + # (e.g. via a command-line flag). + config.default_formatter = "doc" + end + + # Print the 10 slowest examples and example groups at the + # end of the spec run, to help surface which specs are running + # particularly slow. + config.profile_examples = 10 + + # Run specs in random order to surface order dependencies. If you find an + # order dependency and want to debug it, you can fix the order by providing + # the seed, which is printed after each run. + # --seed 1234 + config.order = :random + + # Seed global randomization in this process using the `--seed` CLI option. + # Setting this allows you to use `--seed` to deterministically reproduce + # test failures related to randomization by passing the same `--seed` value + # as the one that triggered the failure. + Kernel.srand config.seed +=end +end