diff --git a/.gitignore b/.gitignore index 835ffa9f..fe656c15 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ # Ignore bundler config /.bundle +# Ignore installed gems +vendor + # Ignore the default SQLite database and yaml_db database files /db/*.sqlite3* /db/data.yml* diff --git a/.travis.yml b/.travis.yml index 7389ef7f..182e6f5d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,3 +21,5 @@ before_script: before_install: - "export DISPLAY=:99.0" - "sh -e /etc/init.d/xvfb start" + - gem install bundler:2.0.1 + diff --git a/Gemfile b/Gemfile index 8072d24d..7b82ab16 100644 --- a/Gemfile +++ b/Gemfile @@ -9,7 +9,7 @@ git_source(:github) do |repo_name| end # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '4.2.11' +gem 'rails', '~> 5.2.3' # Bootstrap gem 'bootstrap-sass' @@ -24,7 +24,7 @@ gem 'compass-rails' gem 'uglifier', '>= 1.3.0' # Use CoffeeScript for .coffee assets and views -gem 'coffee-rails', '~> 4.1.0' +gem 'coffee-rails', '~> 4.2.2' gem 'mini_racer' @@ -59,26 +59,24 @@ gem 'openstax_utilities' gem 'whenever' # Talks to Accounts (latest version is broken) -gem 'omniauth-oauth2', '~> 1.3.1' +gem 'omniauth-oauth2' # OpenStax Accounts integration -gem 'openstax_accounts', '~> 7.12.0' +gem 'openstax_accounts' + # Access control for API's gem 'doorkeeper' # API versioning and documentation gem 'representable', '~> 3.0.0' -gem 'openstax_api', '~> 8.3.0' +gem 'openstax_api' gem 'apipie-rails' gem 'maruku' # Lev framework gem 'lev' -# Ruby dsl for SQL queries -gem 'squeel' - # Contract management gem 'fine_print' @@ -94,8 +92,7 @@ gem 'mimemagic' gem 'mini_magick' # Markdown parsing -# Pinned for Rails 4.X -gem 'kramdown', '1.6.0' +gem 'kramdown' # Read Excel xlsx spreadsheet files gem 'roo' @@ -122,8 +119,7 @@ gem 'acts_as_votable' gem 'scout_apm', '~> 3.0.x' # PostgreSQL database -# Pinned for rails 4.X -gem 'pg', '~> 0.15' +gem 'pg' # HTTP requests gem 'httparty' @@ -134,7 +130,7 @@ gem 'a15k_client', branch: 'master' # Notify developers of Exceptions in production -gem 'openstax_rescue_from', '~> 3.0.0' +gem 'openstax_rescue_from' # Sentry integration (the require disables automatic Rails integration since we use rescue_from) gem 'sentry-raven', require: 'raven/base' @@ -156,6 +152,9 @@ gem 'redis-rails' # Respond to ELB healthchecks in /ping and /ping/ gem 'openstax_healthcheck' +# Reduces boot times through caching; required in config/boot.rb +gem 'bootsnap', '~> 1.4.0', require: false + group :development, :test do # Get env variables from .env file gem 'dotenv-rails' @@ -172,19 +171,19 @@ group :development, :test do # Call 'debugger' anywhere in the code to stop execution and get a debugger console gem 'byebug' + # Some controller test support + gem 'rails-controller-testing' + # Use RSpec for tests gem 'rspec-rails' # Mute asset pipeline log messages - gem 'quiet_assets' # Fixture replacement - # Pinned for rails 4.X - gem 'factory_bot_rails', '< 5.0.0' + gem 'factory_bot_rails' # Lorem Ipsum - # Pinned to avoid 18n problem - gem 'faker', '1.6.6' + gem 'faker' # Database cleaning functionality for tests gem 'database_cleaner' @@ -224,8 +223,9 @@ group :test do # Codecov integration gem 'codecov', require: false - # Test after-commit hooks - gem 'test_after_commit' + # Rubocop + gem 'rubocop-rails' + end group :production do diff --git a/Gemfile.lock b/Gemfile.lock index a7f06a34..51e1e10e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -11,64 +11,73 @@ GIT GEM remote: https://rubygems.org/ specs: - action_interceptor (1.1.1) - rails (>= 3.1, < 5.0) - actionmailer (4.2.11) - actionpack (= 4.2.11) - actionview (= 4.2.11) - activejob (= 4.2.11) + action_interceptor (1.1.2) + rails (>= 3.1) + actioncable (5.2.3) + actionpack (= 5.2.3) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailer (5.2.3) + actionpack (= 5.2.3) + actionview (= 5.2.3) + activejob (= 5.2.3) mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.11) - actionview (= 4.2.11) - activesupport (= 4.2.11) - rack (~> 1.6) - rack-test (~> 0.6.2) - rails-dom-testing (~> 1.0, >= 1.0.5) + rails-dom-testing (~> 2.0) + actionpack (5.2.3) + actionview (= 5.2.3) + activesupport (= 5.2.3) + rack (~> 2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (4.2.11) - activesupport (= 4.2.11) + actionview (5.2.3) + activesupport (= 5.2.3) builder (~> 3.1) - erubis (~> 2.7.0) - rails-dom-testing (~> 1.0, >= 1.0.5) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - active_attr (0.12.0) - activemodel (>= 3.0.2, < 6.0) - activesupport (>= 3.0.2, < 6.0) - activejob (4.2.11) - activesupport (= 4.2.11) - globalid (>= 0.3.0) - activemodel (4.2.11) - activesupport (= 4.2.11) - builder (~> 3.1) - activerecord (4.2.11) - activemodel (= 4.2.11) - activesupport (= 4.2.11) - arel (~> 6.0) - activesupport (4.2.11) - i18n (~> 0.7) + active_attr (0.13.1) + activemodel (>= 3.0.2, < 6.1) + activesupport (>= 3.0.2, < 6.1) + activejob (5.2.3) + activesupport (= 5.2.3) + globalid (>= 0.3.6) + activemodel (5.2.3) + activesupport (= 5.2.3) + activerecord (5.2.3) + activemodel (= 5.2.3) + activesupport (= 5.2.3) + arel (>= 9.0) + activestorage (5.2.3) + actionpack (= 5.2.3) + activerecord (= 5.2.3) + marcel (~> 0.3.1) + activesupport (5.2.3) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) minitest (~> 5.1) - thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) acts_as_votable (0.12.0) addressable (2.6.0) public_suffix (>= 2.0.2, < 4.0) - apipie-rails (0.5.15) + apipie-rails (0.5.16) rails (>= 4.1) - arel (6.0.4) - autoprefixer-rails (9.5.0) + arel (9.0.0) + ast (2.4.0) + autoprefixer-rails (9.6.0) execjs aws-ses (0.6.0) builder mail (> 2.2.5) mime-types xml-simple - baby_squeel (0.3.1) - activerecord (>= 4.0.0) + bindex (0.7.0) + bootsnap (1.4.4) + msgpack (~> 1.0) bootstrap-sass (3.4.1) autoprefixer-rails (>= 5.2.1) sassc (>= 2.0.0) - brakeman (4.5.0) + brakeman (4.5.1) builder (3.2.3) byebug (11.0.1) carrierwave (1.3.1) @@ -86,18 +95,18 @@ GEM json simplecov url - coffee-rails (4.1.1) + coffee-rails (4.2.2) coffee-script (>= 2.2.0) - railties (>= 4.0.0, < 5.1.x) + railties (>= 4.0.0) coffee-rails-source-maps (1.4.0) coffee-script-source (>= 1.6.1) coffee-script (2.4.1) coffee-script-source execjs coffee-script-source (1.12.2) - commontator (4.11.1) + commontator (5.1.0) jquery-rails - rails (>= 3.1) + rails (>= 5.0) compass (1.0.3) chunky_png (~> 1.2) compass-core (~> 1.0.2) @@ -118,15 +127,14 @@ GEM crass (1.0.4) daemons (1.3.1) database_cleaner (1.7.0) - debug_inspector (0.0.3) declarative (0.0.10) deep_cloneable (2.4.0) activerecord (>= 3.1.0, < 6) diff-lcs (1.3) diffy (3.3.0) docile (1.1.5) - doorkeeper (5.0.2) - railties (>= 4.2) + doorkeeper (5.1.0) + railties (>= 5) dotenv (2.7.2) dotenv-rails (2.7.2) dotenv (= 2.7.2) @@ -137,32 +145,31 @@ GEM execjs eco-source (1.1.0.rc.1) ejs (1.1.1) - erubis (2.7.0) + erubi (1.8.0) ethon (0.12.0) ffi (>= 1.3.0) eventmachine (1.2.7) exception_notification (4.3.0) actionmailer (>= 4.0, < 6) activesupport (>= 4.0, < 6) - excon (0.62.0) + excon (0.64.0) execjs (2.7.0) - factory_bot (4.11.1) - activesupport (>= 3.0.0) - factory_bot_rails (4.11.1) - factory_bot (~> 4.11.1) - railties (>= 3.0.0) - faker (1.6.6) - i18n (~> 0.5) + factory_bot (5.0.2) + activesupport (>= 4.2.0) + factory_bot_rails (5.0.2) + factory_bot (~> 5.0.2) + railties (>= 4.2.0) + faker (1.9.3) + i18n (>= 0.7) faraday (0.15.4) multipart-post (>= 1.2, < 3) - ffi (1.10.0) - fine_print (4.0.1) - action_interceptor (>= 1.0) - baby_squeel + ffi (1.11.1) + fine_print (5.0.0) + action_interceptor jquery-rails - rails (>= 4.2) + rails responders - fog-aws (3.4.0) + fog-aws (3.5.0) fog-core (~> 2.1) fog-json (~> 1.1) fog-xml (~> 0.1) @@ -183,12 +190,13 @@ GEM globalid (0.4.2) activesupport (>= 4.2.0) hashie (3.6.0) - httparty (0.16.4) + httparty (0.17.0) mime-types (~> 3.0) multi_xml (>= 0.5.2) - i18n (0.9.5) + i18n (1.6.0) concurrent-ruby (~> 1.0) ipaddress (0.8.3) + jaro_winkler (1.5.2) jquery-rails (4.3.3) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) @@ -196,10 +204,10 @@ GEM jquery-ui-rails (6.0.1) railties (>= 3.2.16) json (2.2.0) - jwt (2.1.0) + jwt (2.2.1) keyword_search (1.5.0) kgio (2.11.2) - kramdown (1.6.0) + kramdown (2.1.0) lev (9.0.1) actionpack (>= 4.2) active_attr @@ -209,8 +217,8 @@ GEM hashie transaction_isolation transaction_retry - libv8 (6.7.288.46.1) - lograge (0.10.0) + libv8 (7.3.492.27.1) + lograge (0.11.1) actionpack (>= 4) activesupport (>= 4) railties (>= 4) @@ -220,22 +228,27 @@ GEM nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) + marcel (0.3.3) + mimemagic (~> 0.3.2) maruku (0.7.3) + method_source (0.9.2) mime-types (3.2.2) mime-types-data (~> 3.2015) - mime-types-data (3.2018.0812) + mime-types-data (3.2019.0331) mimemagic (0.3.3) mini_magick (4.9.3) mini_mime (1.0.1) mini_portile2 (2.4.0) - mini_racer (0.2.4) - libv8 (>= 6.3) + mini_racer (0.2.6) + libv8 (>= 6.9.411) minitest (5.11.3) + msgpack (1.2.10) multi_json (1.13.1) multi_xml (0.6.0) - multipart-post (2.0.0) + multipart-post (2.1.1) nifty-generators (0.4.6) - nokogiri (1.10.2) + nio4r (2.3.1) + nokogiri (1.10.3) mini_portile2 (~> 2.4.0) nokogumbo (2.0.1) nokogiri (~> 1.8, >= 1.8.4) @@ -245,33 +258,33 @@ GEM multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) - oj (3.7.11) + oj (3.7.12) oj_mimic_json (1.0.1) omniauth (1.9.0) hashie (>= 3.4.6, < 3.7.0) rack (>= 1.6.2, < 3) - omniauth-oauth2 (1.3.1) - oauth2 (~> 1.0) - omniauth (~> 1.2) - openstax_accounts (7.12.0) - action_interceptor (>= 1.0) - keyword_search (>= 1.0.0) - lev (>= 2.2.1) - oauth2 (>= 0.5.0) - omniauth (>= 1.1) - omniauth-oauth2 (>= 1.1) - openstax_api (>= 3.1.0) - openstax_utilities (>= 4.1.0) + omniauth-oauth2 (1.6.0) + oauth2 (~> 1.1) + omniauth (~> 1.9) + openstax_accounts (8.0.0) + action_interceptor + keyword_search + lev + oauth2 + omniauth + omniauth-oauth2 + openstax_api + openstax_utilities pg - rails (>= 4.1, < 5.0) - representable (>= 2.0) - roar (>= 1.0) - openstax_api (8.3.2) + rails + representable + roar + openstax_api (9.0.0) doorkeeper (>= 2.0) exception_notification (>= 4.0) lev (>= 1.0.0) openstax_utilities (>= 4.2.0) - rails (>= 3.1, < 5.0) + rails (>= 3.1) representable (>= 2.4, < 4.0) responders roar (>= 1.0) @@ -279,61 +292,64 @@ GEM uber (< 0.1.0) openstax_healthcheck (0.0.3) rails (>= 3.0) - openstax_rescue_from (3.0.0) + openstax_rescue_from (4.0.0) rails (>= 3.1, < 6.0) openstax_utilities (4.2.3) keyword_search lev rails (>= 3.1) pager (1.0.1) - parallel (1.16.0) - parallel_tests (2.28.0) + parallel (1.17.0) + parallel_tests (2.29.0) parallel - pg (0.21.0) - polyamorous (1.1.0) - activerecord (>= 3.0) - public_suffix (3.0.3) - quiet_assets (1.1.0) - railties (>= 3.1, < 5.0) - rack (1.6.11) - rack-test (0.6.3) - rack (>= 1.0) + parser (2.6.3.0) + ast (~> 2.4.0) + pg (1.1.4) + public_suffix (3.1.0) + rack (2.0.7) + rack-test (1.1.0) + rack (>= 1.0, < 3) railroady (1.5.3) - rails (4.2.11) - actionmailer (= 4.2.11) - actionpack (= 4.2.11) - actionview (= 4.2.11) - activejob (= 4.2.11) - activemodel (= 4.2.11) - activerecord (= 4.2.11) - activesupport (= 4.2.11) - bundler (>= 1.3.0, < 2.0) - railties (= 4.2.11) - sprockets-rails - rails-deprecated_sanitizer (1.0.3) - activesupport (>= 4.2.0.alpha) - rails-dom-testing (1.0.9) - activesupport (>= 4.2.0, < 5.0) - nokogiri (~> 1.6) - rails-deprecated_sanitizer (>= 1.0.1) - rails-erd (1.5.2) - activerecord (>= 3.2) - activesupport (>= 3.2) + rails (5.2.3) + actioncable (= 5.2.3) + actionmailer (= 5.2.3) + actionpack (= 5.2.3) + actionview (= 5.2.3) + activejob (= 5.2.3) + activemodel (= 5.2.3) + activerecord (= 5.2.3) + activestorage (= 5.2.3) + activesupport (= 5.2.3) + bundler (>= 1.3.0) + railties (= 5.2.3) + sprockets-rails (>= 2.0.0) + rails-controller-testing (1.0.4) + actionpack (>= 5.0.1.x) + actionview (>= 5.0.1.x) + activesupport (>= 5.0.1.x) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-erd (1.6.0) + activerecord (>= 4.2) + activesupport (>= 4.2) choice (~> 0.2.0) ruby-graphviz (~> 1.2) rails-html-sanitizer (1.0.4) loofah (~> 2.2, >= 2.2.2) - railties (4.2.11) - actionpack (= 4.2.11) - activesupport (= 4.2.11) + railties (5.2.3) + actionpack (= 5.2.3) + activesupport (= 5.2.3) + method_source rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) + thor (>= 0.19.0, < 2.0) + rainbow (3.0.0) raindrops (0.19.0) rake (12.3.2) rb-fsevent (0.10.3) rb-inotify (0.10.0) ffi (~> 1.0) - redis (4.1.0) + redis (4.1.2) redis-actionpack (5.0.2) actionpack (>= 4.0, < 6) redis-rack (>= 1, < 3) @@ -350,7 +366,7 @@ GEM redis-store (>= 1.2, < 2) redis-store (1.6.0) redis (>= 2.2, < 5) - remotipart (1.4.2) + remotipart (1.4.3) representable (3.0.0) declarative (~> 0.0.5) uber (~> 0.0.15) @@ -359,7 +375,7 @@ GEM responders (2.4.1) actionpack (>= 4.2.0, < 6.0) railties (>= 4.2.0, < 6.0) - rinku (2.0.5) + rinku (2.0.6) roar (1.0.3) representable (>= 2.0.1, <= 3.0.0) roar-rails (1.0.1) @@ -378,7 +394,7 @@ GEM rspec-mocks (~> 3.8.0) rspec-core (3.8.0) rspec-support (~> 3.8.0) - rspec-expectations (3.8.2) + rspec-expectations (3.8.3) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-instafail (1.0.0) @@ -395,8 +411,19 @@ GEM rspec-mocks (~> 3.8.0) rspec-support (~> 3.8.0) rspec-support (3.8.0) + rubocop (0.71.0) + jaro_winkler (~> 1.5.1) + parallel (~> 1.10) + parser (>= 2.6) + rainbow (>= 2.2.2, < 4.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 1.7) + rubocop-rails (2.0.0) + rack (>= 2.0) + rubocop (>= 0.70.0) ruby-graphviz (1.2.4) - rubyzip (1.2.2) + ruby-progressbar (1.10.1) + rubyzip (1.2.3) sanitize (5.0.0) crass (~> 1.0.2) nokogiri (>= 1.8.0) @@ -421,9 +448,8 @@ GEM json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) - sortability (0.1.0) + sortability (1.0.0) rails - squeel sprockets (3.7.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) @@ -431,12 +457,6 @@ GEM actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) - squeel (1.2.3) - activerecord (>= 3.0) - activesupport (>= 3.0) - polyamorous (~> 1.1.0) - test_after_commit (1.2.2) - activerecord (>= 3.2, < 5.0) test_xml (0.1.8) diffy (~> 3.0) nokogiri (>= 1.3.2) @@ -463,18 +483,23 @@ GEM uber (0.0.15) uglifier (4.1.20) execjs (>= 0.3.0, < 3) - unicorn (5.5.0) + unicode-display_width (1.6.0) + unicorn (5.5.1) kgio (~> 2.6) raindrops (~> 0.7) unicorn-worker-killer (0.4.4) get_process_mem (~> 0) unicorn (>= 4, < 6) url (0.3.2) - web-console (3.3.0) - activemodel (>= 4.2) - debug_inspector - railties (>= 4.2) - whenever (0.10.0) + web-console (3.7.0) + actionview (>= 5.0) + activemodel (>= 5.0) + bindex (>= 0.4.0) + railties (>= 5.0) + websocket-driver (0.7.0) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.3) + whenever (0.11.0) chronic (>= 0.6.3) xml-simple (1.1.5) @@ -488,6 +513,7 @@ DEPENDENCIES apipie-rails autoprefixer-rails aws-ses (~> 0.6.0) + bootsnap (~> 1.4.0) bootstrap-sass brakeman byebug @@ -495,7 +521,7 @@ DEPENDENCIES cheat codeclimate-test-reporter codecov - coffee-rails (~> 4.1.0) + coffee-rails (~> 4.2.2) coffee-rails-source-maps commontator compass-rails @@ -505,15 +531,15 @@ DEPENDENCIES dotenv-rails eco ejs - factory_bot_rails (< 5.0.0) - faker (= 1.6.6) + factory_bot_rails + faker fine_print fog-aws httparty jquery-rails jquery-ui-rails keyword_search - kramdown (= 1.6.0) + kramdown lev lograge maruku @@ -523,17 +549,17 @@ DEPENDENCIES nifty-generators oj oj_mimic_json - omniauth-oauth2 (~> 1.3.1) - openstax_accounts (~> 7.12.0) - openstax_api (~> 8.3.0) + omniauth-oauth2 + openstax_accounts + openstax_api openstax_healthcheck - openstax_rescue_from (~> 3.0.0) + openstax_rescue_from openstax_utilities parallel_tests - pg (~> 0.15) - quiet_assets + pg railroady - rails (= 4.2.11) + rails (~> 5.2.3) + rails-controller-testing rails-erd rails-html-sanitizer redis-rails @@ -544,14 +570,13 @@ DEPENDENCIES roo rspec-instafail rspec-rails + rubocop-rails sanitize sass-rails (~> 5.0) scout_apm (~> 3.0.x) sentry-raven shoulda-matchers sortability - squeel - test_after_commit thin timecop turbolinks @@ -562,4 +587,4 @@ DEPENDENCIES whenever BUNDLED WITH - 1.17.3 + 2.0.1 diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb index 0f8e972d..516932ec 100644 --- a/app/controllers/admin/base_controller.rb +++ b/app/controllers/admin/base_controller.rb @@ -1,8 +1,8 @@ module Admin class BaseController < ApplicationController - skip_before_filter :authenticate_user! if Rails.env.development? - before_filter :authenticate_admin! unless Rails.env.development? + skip_before_action :authenticate_user! if Rails.env.development? + before_action :authenticate_admin! unless Rails.env.development? fine_print_skip :general_terms_of_use, :privacy_policy diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 341bff8f..9a0404dc 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -1,7 +1,7 @@ module Admin class UsersController < BaseController - before_filter :set_user, only: [:show, :edit, :update, :become, :delete, :undelete] + before_action :set_user, only: [:show, :edit, :update, :become, :delete, :undelete] # GET /users def index diff --git a/app/controllers/api/v1/attachments_controller.rb b/app/controllers/api/v1/attachments_controller.rb index 44b76988..2117ca65 100644 --- a/app/controllers/api/v1/attachments_controller.rb +++ b/app/controllers/api/v1/attachments_controller.rb @@ -3,8 +3,8 @@ class AttachmentsController < OpenStax::Api::V1::ApiController include Exercises::Finders - before_filter :find_exercise_or_create_draft, only: [:create] - before_filter :find_exercise, only: [:destroy] + before_action :find_exercise_or_create_draft, only: [:create] + before_action :find_exercise, only: [:destroy] ########## # create # diff --git a/app/controllers/api/v1/community_solutions_controller.rb b/app/controllers/api/v1/community_solutions_controller.rb index 717cabd9..1d3ebe4b 100644 --- a/app/controllers/api/v1/community_solutions_controller.rb +++ b/app/controllers/api/v1/community_solutions_controller.rb @@ -1,7 +1,7 @@ module Api::V1 class CommunitySolutionsController < OpenStax::Api::V1::ApiController - before_filter :get_community_solution, only: [:show, :update, :destroy] + before_action :get_community_solution, only: [:show, :update, :destroy] resource_description do api_versions "v1" diff --git a/app/controllers/api/v1/exercises_controller.rb b/app/controllers/api/v1/exercises_controller.rb index 1872f130..2cc1334a 100644 --- a/app/controllers/api/v1/exercises_controller.rb +++ b/app/controllers/api/v1/exercises_controller.rb @@ -3,8 +3,8 @@ class ExercisesController < OpenStax::Api::V1::ApiController include ::Exercises::Finders - before_filter :find_exercise_or_create_draft, only: [:show, :update] - before_filter :find_exercise, only: [:destroy] + before_action :find_exercise_or_create_draft, only: [:show, :update] + before_action :find_exercise, only: [:destroy] resource_description do api_versions "v1" @@ -119,10 +119,12 @@ def create OSU::AccessPolicy.require_action_allowed!(:create, current_api_user, exercise) - if exercise.save && publication_group.save + if publication.save && publication_group.save && exercise.save respond_with exercise, create_options.merge(represent_with_options) else - render_api_errors(publication_group.errors) || render_api_errors(exercise.errors) + render_api_errors(publication.errors) || + render_api_errors(publication_group.errors) || + render_api_errors(exercise.errors) raise ActiveRecord::Rollback end end diff --git a/app/controllers/api/v1/publications_controller.rb b/app/controllers/api/v1/publications_controller.rb index 14a44469..a39fed99 100644 --- a/app/controllers/api/v1/publications_controller.rb +++ b/app/controllers/api/v1/publications_controller.rb @@ -7,7 +7,7 @@ class PublicationsController < OpenStax::Api::V1::ApiController 'VocabTerm' => 'Api::V1::Vocabs::TermWithDistractorsAndExerciseIdsRepresenter', } - before_filter :get_publishable + before_action :get_publishable resource_description do api_versions "v1" diff --git a/app/controllers/api/v1/vocab_terms_controller.rb b/app/controllers/api/v1/vocab_terms_controller.rb index 33c9aa18..19182b1b 100644 --- a/app/controllers/api/v1/vocab_terms_controller.rb +++ b/app/controllers/api/v1/vocab_terms_controller.rb @@ -1,8 +1,8 @@ module Api::V1 class VocabTermsController < OpenStax::Api::V1::ApiController - before_filter :get_vocab_term_or_create_draft, only: [:show, :update] - before_filter :get_vocab_term, only: :destroy + before_action :get_vocab_term_or_create_draft, only: [:show, :update] + before_action :get_vocab_term, only: :destroy resource_description do api_versions "v1" diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c83f6fb7..207f1ea3 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -7,7 +7,7 @@ class ApplicationController < ActionController::Base include Lev::HandleWith - before_filter :authenticate_user!, :valid_user! + before_action :authenticate_user!, :valid_user! fine_print_require :general_terms_of_use, :privacy_policy diff --git a/app/controllers/dev/base_controller.rb b/app/controllers/dev/base_controller.rb index 312de862..12027b9f 100644 --- a/app/controllers/dev/base_controller.rb +++ b/app/controllers/dev/base_controller.rb @@ -4,9 +4,9 @@ module Dev class BaseController < ApplicationController - before_filter :development_or_test! + before_action :development_or_test! - skip_before_filter :authenticate_user! + skip_before_action :authenticate_user! fine_print_skip :general_terms_of_use, :privacy_policy protected diff --git a/app/controllers/static_pages_controller.rb b/app/controllers/static_pages_controller.rb index 57f2b1d4..9a911150 100644 --- a/app/controllers/static_pages_controller.rb +++ b/app/controllers/static_pages_controller.rb @@ -2,7 +2,7 @@ class StaticPagesController < ApplicationController respond_to :html - skip_before_filter :authenticate_user!, + skip_before_action :authenticate_user!, only: [:about, :contact, :copyright, :developers, :help, :privacy, :share, :status, :terms] fine_print_skip :general_terms_of_use, :privacy_policy, diff --git a/app/controllers/webview_controller.rb b/app/controllers/webview_controller.rb index 72fa2ba7..3012b842 100644 --- a/app/controllers/webview_controller.rb +++ b/app/controllers/webview_controller.rb @@ -4,7 +4,7 @@ class WebviewController < ApplicationController layout :resolve_layout - skip_before_filter :authenticate_user!, only: :home + skip_before_action :authenticate_user!, only: :home fine_print_skip :general_terms_of_use, :privacy_policy, only: :home def home diff --git a/app/models/administrator.rb b/app/models/administrator.rb index c09bc8a1..85cc0f73 100644 --- a/app/models/administrator.rb +++ b/app/models/administrator.rb @@ -1,7 +1,7 @@ -class Administrator < ActiveRecord::Base +class Administrator < ApplicationRecord belongs_to :user - validates :user, presence: true, uniqueness: true + validates :user, uniqueness: true end diff --git a/app/models/answer.rb b/app/models/answer.rb index a4e2ae17..8201884b 100644 --- a/app/models/answer.rb +++ b/app/models/answer.rb @@ -1,4 +1,4 @@ -class Answer < ActiveRecord::Base +class Answer < ApplicationRecord attr_accessor :temp_id @@ -10,7 +10,6 @@ class Answer < ActiveRecord::Base has_many :combo_choice_answers, dependent: :destroy - validates :question, presence: true validates :content, presence: true end diff --git a/app/models/application_record.rb b/app/models/application_record.rb new file mode 100644 index 00000000..10a4cba8 --- /dev/null +++ b/app/models/application_record.rb @@ -0,0 +1,3 @@ +class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true +end diff --git a/app/models/attachment.rb b/app/models/attachment.rb index cfcaa6cd..9003a520 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -1,4 +1,4 @@ -class Attachment < ActiveRecord::Base +class Attachment < ApplicationRecord mount_uploader :asset, AssetUploader @@ -7,7 +7,6 @@ class Attachment < ActiveRecord::Base before_update { raise ActiveRecord::ReadOnlyRecord } # Prevent updates validates :asset, presence: true - validates :parent, presence: true validate :unique_asset def filename @@ -22,11 +21,9 @@ def remove_asset! def unique_asset return if asset.nil? || parent.nil? - return unless Attachment.where {(id != my{id}) & \ - (parent == my{parent}) & \ - (asset == my{asset.identifier})}.exists? + return unless Attachment.where.not(id: id).where({parent_id: parent.id, asset: asset.identifier}).exists? errors.add(:asset, 'has already been associated with this resource') - false + throw(:abort) end end diff --git a/app/models/author.rb b/app/models/author.rb index 7b503c53..a2ef81c9 100644 --- a/app/models/author.rb +++ b/app/models/author.rb @@ -1,11 +1,10 @@ -class Author < ActiveRecord::Base +class Author < ApplicationRecord sortable_belongs_to :publication, inverse_of: :authors belongs_to :user - validates :publication, presence: true - validates :user, presence: true, uniqueness: { scope: :publication_id } + validates :user, uniqueness: { scope: :publication_id } delegate :name, to: :user diff --git a/app/models/class_license.rb b/app/models/class_license.rb index eeb6a364..9467d771 100644 --- a/app/models/class_license.rb +++ b/app/models/class_license.rb @@ -1,4 +1,4 @@ -class ClassLicense < ActiveRecord::Base +class ClassLicense < ApplicationRecord sortable_class scope: :class_name @@ -7,7 +7,6 @@ class ClassLicense < ActiveRecord::Base has_many :same_class, class_name: 'ClassLicense', foreign_key: :class_name, primary_key: :class_name - validates :license, presence: true validates :class_name, presence: true, uniqueness: { scope: :license_id } end diff --git a/app/models/collaborator_solution.rb b/app/models/collaborator_solution.rb index 18d733a3..16086c7d 100644 --- a/app/models/collaborator_solution.rb +++ b/app/models/collaborator_solution.rb @@ -1,3 +1,3 @@ -class CollaboratorSolution < ActiveRecord::Base +class CollaboratorSolution < ApplicationRecord solution end diff --git a/app/models/combo_choice.rb b/app/models/combo_choice.rb index 417cc357..cbf6811c 100644 --- a/app/models/combo_choice.rb +++ b/app/models/combo_choice.rb @@ -1,10 +1,9 @@ -class ComboChoice < ActiveRecord::Base +class ComboChoice < ApplicationRecord belongs_to :stem has_many :combo_choice_answers, dependent: :destroy - validates :stem, presence: true validates :correctness, presence: true, numericality: { greater_than_or_equal_to: 0.0, less_than_or_equal_to: 1.0 } diff --git a/app/models/combo_choice_answer.rb b/app/models/combo_choice_answer.rb index 5768674a..091354ae 100644 --- a/app/models/combo_choice_answer.rb +++ b/app/models/combo_choice_answer.rb @@ -1,10 +1,9 @@ -class ComboChoiceAnswer < ActiveRecord::Base +class ComboChoiceAnswer < ApplicationRecord belongs_to :combo_choice belongs_to :answer - validates :combo_choice, presence: true - validates :answer, presence: true, uniqueness: { scope: :combo_choice_id } + validates :answer, uniqueness: { scope: :combo_choice_id } validate :same_question protected diff --git a/app/models/community_solution.rb b/app/models/community_solution.rb index b18278bb..fd57a8ce 100644 --- a/app/models/community_solution.rb +++ b/app/models/community_solution.rb @@ -1,4 +1,4 @@ -class CommunitySolution < ActiveRecord::Base +class CommunitySolution < ApplicationRecord publishable solution end diff --git a/app/models/copyright_holder.rb b/app/models/copyright_holder.rb index e0ec514a..4027d4e4 100644 --- a/app/models/copyright_holder.rb +++ b/app/models/copyright_holder.rb @@ -1,11 +1,10 @@ -class CopyrightHolder < ActiveRecord::Base +class CopyrightHolder < ApplicationRecord sortable_belongs_to :publication, inverse_of: :copyright_holders belongs_to :user - validates :publication, presence: true - validates :user, presence: true, uniqueness: { scope: :publication_id } + validates :user, uniqueness: { scope: :publication_id } delegate :name, to: :user diff --git a/app/models/deputization.rb b/app/models/deputization.rb index 3ba86426..de1cf05c 100644 --- a/app/models/deputization.rb +++ b/app/models/deputization.rb @@ -1,10 +1,8 @@ -class Deputization < ActiveRecord::Base +class Deputization < ApplicationRecord belongs_to :deputizer, class_name: 'User', inverse_of: :child_deputizations belongs_to :deputy, polymorphic: true - validates :deputy, presence: true - validates :deputizer, presence: true, - uniqueness: { scope: [:deputy_type, :deputy_id] } + validates :deputizer, uniqueness: { scope: [:deputy_type, :deputy_id] } end diff --git a/app/models/derivation.rb b/app/models/derivation.rb index dded3686..8597cbb2 100644 --- a/app/models/derivation.rb +++ b/app/models/derivation.rb @@ -1,9 +1,8 @@ -class Derivation < ActiveRecord::Base +class Derivation < ApplicationRecord sortable_belongs_to :derived_publication, class_name: 'Publication', inverse_of: :sources - belongs_to :source_publication, class_name: 'Publication', inverse_of: :derivations + belongs_to :source_publication, class_name: 'Publication', inverse_of: :derivations, optional: true - validates :derived_publication, presence: true validates :source_publication, uniqueness: { scope: :derived_publication_id, allow_nil: true } validate :different_publications, :source_or_custom diff --git a/app/models/exercise.rb b/app/models/exercise.rb index 7256b588..d7856889 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -1,4 +1,4 @@ -class Exercise < ActiveRecord::Base +class Exercise < ApplicationRecord EQUALITY_ASSOCIATIONS = [ :attachments, @@ -87,7 +87,7 @@ class Exercise < ActiveRecord::Base sortable_has_many :questions, dependent: :destroy, autosave: true, inverse_of: :exercise - belongs_to :vocab_term, touch: true + belongs_to :vocab_term, touch: true, optional: true scope :can_release_to_a15k, -> { where(release_to_a15k: true) } scope :not_released_to_a15k, -> { where(a15k_identifier: nil) } @@ -138,11 +138,9 @@ def before_publication question.stems.each do |stem| next if stem.stem_answers.empty? || stem.stem_answers.any?{ |sa| sa.is_correct? } errors.add(:base, 'has a question with only incorrect answers') - return false + throw(:abort) end end - - true end protected @@ -150,7 +148,7 @@ def before_publication def has_questions return unless questions.first.nil? errors.add(:questions, "can't be blank") - false + throw(:abort) end end diff --git a/app/models/exercise_tag.rb b/app/models/exercise_tag.rb index 0c6a9c7b..d284542f 100644 --- a/app/models/exercise_tag.rb +++ b/app/models/exercise_tag.rb @@ -1,7 +1,6 @@ -class ExerciseTag < ActiveRecord::Base +class ExerciseTag < ApplicationRecord belongs_to :exercise belongs_to :tag - validates :exercise, presence: true - validates :tag, presence: true, uniqueness: { scope: :exercise_id } + validates :tag, uniqueness: { scope: :exercise_id } end diff --git a/app/models/hint.rb b/app/models/hint.rb index 66d87a1f..c1e6bee7 100644 --- a/app/models/hint.rb +++ b/app/models/hint.rb @@ -1,8 +1,7 @@ -class Hint < ActiveRecord::Base +class Hint < ApplicationRecord sortable_belongs_to :question, inverse_of: :hints - validates :question, presence: true validates :content, presence: true end diff --git a/app/models/license.rb b/app/models/license.rb index 46ee31df..1f1667a2 100644 --- a/app/models/license.rb +++ b/app/models/license.rb @@ -1,4 +1,4 @@ -class License < ActiveRecord::Base +class License < ApplicationRecord has_many :publications, dependent: :destroy has_many :class_licenses, dependent: :destroy diff --git a/app/models/license_compatibility.rb b/app/models/license_compatibility.rb index 3c3cc7b7..9c9b6db9 100644 --- a/app/models/license_compatibility.rb +++ b/app/models/license_compatibility.rb @@ -1,11 +1,10 @@ -class LicenseCompatibility < ActiveRecord::Base +class LicenseCompatibility < ApplicationRecord belongs_to :original_license, class_name: 'License', inverse_of: :combined_license_compatibilities belongs_to :combined_license, class_name: 'License', inverse_of: :original_license_compatibilities - validates :original_license, presence: true - validates :combined_license, presence: true, uniqueness: { scope: :original_license_id } + validates :combined_license, uniqueness: { scope: :original_license_id } end diff --git a/app/models/list.rb b/app/models/list.rb index c776dc46..1b552e1c 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -1,4 +1,4 @@ -class List < ActiveRecord::Base +class List < ApplicationRecord publishable diff --git a/app/models/list_editor.rb b/app/models/list_editor.rb index 8312e4a9..d2e356b1 100644 --- a/app/models/list_editor.rb +++ b/app/models/list_editor.rb @@ -1,9 +1,8 @@ -class ListEditor < ActiveRecord::Base +class ListEditor < ApplicationRecord belongs_to :list, inverse_of: :list_editors belongs_to :editor, polymorphic: true - validates :list, presence: true, uniqueness: { scope: [:editor_type, :editor_id] } - validates :editor, presence: true + validates :list, uniqueness: { scope: [:editor_type, :editor_id] } end diff --git a/app/models/list_nesting.rb b/app/models/list_nesting.rb index 781cdcf3..ffb153a0 100644 --- a/app/models/list_nesting.rb +++ b/app/models/list_nesting.rb @@ -1,9 +1,8 @@ -class ListNesting < ActiveRecord::Base +class ListNesting < ApplicationRecord belongs_to :parent_list, class_name: 'List', inverse_of: :child_list_nestings belongs_to :child_list, class_name: 'List', inverse_of: :parent_list_nesting - validates :parent_list, presence: true - validates :child_list, presence: true, uniqueness: true + validates :child_list, uniqueness: true end diff --git a/app/models/list_owner.rb b/app/models/list_owner.rb index c3f75480..9bea0f80 100644 --- a/app/models/list_owner.rb +++ b/app/models/list_owner.rb @@ -1,9 +1,8 @@ -class ListOwner < ActiveRecord::Base +class ListOwner < ApplicationRecord belongs_to :list, inverse_of: :list_owners belongs_to :owner, polymorphic: true - validates :list, presence: true, uniqueness: { scope: [:owner_type, :owner_id] } - validates :owner, presence: true + validates :list, uniqueness: { scope: [:owner_type, :owner_id] } end diff --git a/app/models/list_publication_group.rb b/app/models/list_publication_group.rb index e47c6be5..4a788bb4 100644 --- a/app/models/list_publication_group.rb +++ b/app/models/list_publication_group.rb @@ -1,9 +1,8 @@ -class ListPublicationGroup < ActiveRecord::Base +class ListPublicationGroup < ApplicationRecord sortable_belongs_to :list, inverse_of: :list_publication_groups belongs_to :publication_group, inverse_of: :list_publication_groups - validates :list, presence: true - validates :publication_group, presence: true, uniqueness: { scope: :list_id } + validates :publication_group, uniqueness: { scope: :list_id } end diff --git a/app/models/list_reader.rb b/app/models/list_reader.rb index cc7e7e7a..bfb5b0d3 100644 --- a/app/models/list_reader.rb +++ b/app/models/list_reader.rb @@ -1,9 +1,8 @@ -class ListReader < ActiveRecord::Base +class ListReader < ApplicationRecord belongs_to :list, inverse_of: :list_readers belongs_to :reader, polymorphic: true - validates :list, presence: true, uniqueness: { scope: [:reader_type, :reader_id] } - validates :reader, presence: true + validates :list, uniqueness: { scope: [:reader_type, :reader_id] } end diff --git a/app/models/logic.rb b/app/models/logic.rb index d6386608..8763d53f 100644 --- a/app/models/logic.rb +++ b/app/models/logic.rb @@ -1,10 +1,9 @@ -class Logic < ActiveRecord::Base +class Logic < ApplicationRecord belongs_to :parent, polymorphic: true, inverse_of: :logic has_many :logic_variables, dependent: :destroy - validates :parent, presence: true validates :parent_id, uniqueness: { scope: :parent_type } validates :language, presence: true, inclusion: { in: Language.all } validates :code, presence: true diff --git a/app/models/logic_variable.rb b/app/models/logic_variable.rb index e93a32aa..181306fc 100644 --- a/app/models/logic_variable.rb +++ b/app/models/logic_variable.rb @@ -1,4 +1,4 @@ -class LogicVariable < ActiveRecord::Base +class LogicVariable < ApplicationRecord VARIABLE_REGEX = /\A[_a-zA-Z]{1}\w*\z/ @@ -14,7 +14,6 @@ class LogicVariable < ActiveRecord::Base has_many :logic_variable_values, dependent: :destroy - validates :logic, presence: true validates :variable, presence: true, uniqueness: { scope: :logic_id }, format: { with: VARIABLE_REGEX }, exclusion: { in: RESERVED_WORDS } diff --git a/app/models/logic_variable_value.rb b/app/models/logic_variable_value.rb index 0ca85403..52856cfc 100644 --- a/app/models/logic_variable_value.rb +++ b/app/models/logic_variable_value.rb @@ -1,8 +1,7 @@ -class LogicVariableValue < ActiveRecord::Base +class LogicVariableValue < ApplicationRecord belongs_to :logic_variable - validates :logic_variable, presence: true validates :seed, presence: true, uniqueness: { scope: :logic_variable_id } validates :value, presence: true diff --git a/app/models/publication.rb b/app/models/publication.rb index 26eb3d9f..3c4dbfe5 100644 --- a/app/models/publication.rb +++ b/app/models/publication.rb @@ -1,8 +1,8 @@ -class Publication < ActiveRecord::Base +class Publication < ApplicationRecord belongs_to :publication_group, inverse_of: :publications belongs_to :publishable, polymorphic: true, inverse_of: :publication, touch: true - belongs_to :license + belongs_to :license, optional: true sortable_has_many :authors, dependent: :destroy, inverse_of: :publication sortable_has_many :copyright_holders, dependent: :destroy, inverse_of: :publication @@ -17,7 +17,6 @@ class Publication < ActiveRecord::Base delegate :group_uuid, :number, :nickname, :nickname=, to: :publication_group - validates :publication_group, :publishable, presence: true validates :publishable_id, uniqueness: { scope: :publishable_type } validates :uuid, presence: true, uniqueness: true validates :version, presence: true, uniqueness: { scope: :publication_group_id }, @@ -39,20 +38,23 @@ class Publication < ActiveRecord::Base scope :with_id, ->(id) do nn, vv = id.to_s.split('@') - joins(:publication_group).where do - wheres = (publication_group.uuid == nn) | (publication_group.number == nn) + pub = Publication.arel_table + pubg = PublicationGroup.arel_table - case vv + wheres = pubg[:uuid].eq(nn).or(pubg[:number].eq(nn)) + case vv when NilClass - (wheres | (uuid == nn)) & (published_at != nil) + wheres = wheres.or(pub[:uuid].eq(nn)).and(pub[:published_at].not_eq(nil)) when 'draft', 'd' - wheres & (published_at == nil) + wheres = wheres.and(pub[:published_at].eq(nil)) when 'latest' wheres else - wheres & (version == vv) - end - end.order {[publication_group.number.asc, version.desc]} + wheres = wheres.and(pub[:version].eq(vv)) + end + + joins(publication: :publication_group).where(wheres + ).order( [pubg[:number].asc, pub[:version].desc] ) end scope :visible_for, ->(options) do @@ -64,22 +66,33 @@ class Publication < ActiveRecord::Base next all if user.administrator user_id = user.id - joins do - [ - authors, - copyright_holders, - publication_group.list_publication_groups.outer.list.outer.list_owners, - publication_group.list_publication_groups.outer.list.outer.list_editors, - publication_group.list_publication_groups.outer.list.outer.list_readers - ].map(&:outer) - end.where do - (published_at != nil ) | - (authors.user_id == user_id ) | - (copyright_holders.user_id == user_id ) | - ((list_owners.owner_id == user_id) & (list_owners.owner_type == 'User')) | - ((list_editors.editor_id == user_id) & (list_editors.editor_type == 'User')) | - ((list_readers.reader_id == user_id) & (list_readers.reader_type == 'User')) - end + pub = Publication.arel_table + au = Author.arel_table + cw = CopyrightHolder.arel_table + pubg = PublicationGroup.arel_table + lpg = ListPublicationGroup.arel_table + l_own = ListOwner.arel_table + l_edit = ListEditor.arel_table + l_read = ListReader.arel_table + + me = self.arel_table + + joins(me.join(pub).on(pub[:publishable_id].eq(me[:id]), pub[:publishable_type].eq(self.name)) + .join(au).on(au[:publication_id].eq(pub[:id])) + .join(cw).on(cw[:publication_id].eq(pub[:id])) + .join(pubg).on(pub[:publication_group_id].eq(pubg[:id])) + .outer_join(lpg).on(lpg[:publication_group_id].eq(pubg[:id])) + .outer_join(l_own).on(l_own[:list_id].eq(lpg[:id])) + .outer_join(l_edit).on(l_edit[:list_id].eq(lpg[:id])) + .outer_join(l_read).on(l_read[:list_id].eq(lpg[:id])).join_sources + ).where( + pub[:published_at].not_eq(nil) + .or(au[:user_id].eq(user_id)) + .or(cw[:user_id].eq(user_id)) + .or(l_own[:owner_id].eq(user_id).and(l_own[:owner_type].eq('User'))) + .or(l_edit[:editor_id].eq(user_id).and(l_edit[:editor_type].eq('User'))) + .or(l_read[:reader_id].eq(user_id).and(l_read[:reader_type].eq('User')))) + end # By default, returns both the latest published version and the latest draft, if any @@ -206,7 +219,7 @@ def valid_license return if license.nil? || license.valid_for?(publishable_type) errors.add(:license, "is invalid for #{publishable_type}") - false + throw(:abort) end def valid_publication_group @@ -219,20 +232,23 @@ def valid_publication_group errors.add(:publication_group, "is invalid for #{publishable_type}") \ if publication_group.publishable_type != publishable_type publication_group.errors.each { |attribute, error| errors.add attribute, error } - false + throw(:abort) end def before_publication return if published_at.nil? || publishable.nil? - publishable.before_publication + catch(:abort) do + publishable.before_publication + end + return if publishable.errors.empty? publishable.errors.full_messages.each do |message| errors.add(publishable_type.underscore.to_sym, message) end - false + throw(:abort) end def after_publication @@ -251,7 +267,7 @@ def after_publication errors.add(publishable_type.underscore.to_sym, message) end - false + throw(:abort) end end diff --git a/app/models/publication_group.rb b/app/models/publication_group.rb index e3eb0149..2d21b792 100644 --- a/app/models/publication_group.rb +++ b/app/models/publication_group.rb @@ -1,4 +1,4 @@ -class PublicationGroup < ActiveRecord::Base +class PublicationGroup < ApplicationRecord has_many :publications, dependent: :destroy, inverse_of: :publication_group, autosave: true diff --git a/app/models/question.rb b/app/models/question.rb index 3580a73f..de79ee4a 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -1,4 +1,4 @@ -class Question < ActiveRecord::Base +class Question < ApplicationRecord attr_accessor :temp_id @@ -8,7 +8,7 @@ class Question < ActiveRecord::Base has_many :stems, dependent: :destroy - sortable_has_many :answers, dependent: :destroy, inverse_of: :question + sortable_has_many :answers, dependent: :destroy, inverse_of: :question, autosave: true has_many :collaborator_solutions, dependent: :destroy has_many :community_solutions, dependent: :destroy @@ -23,6 +23,4 @@ class Question < ActiveRecord::Base foreign_key: :parent_question_id, dependent: :destroy, inverse_of: :parent_question - validates :exercise, presence: true - end diff --git a/app/models/question_dependency.rb b/app/models/question_dependency.rb index 732698a1..7755176f 100644 --- a/app/models/question_dependency.rb +++ b/app/models/question_dependency.rb @@ -1,13 +1,11 @@ -class QuestionDependency < ActiveRecord::Base +class QuestionDependency < ApplicationRecord belongs_to :parent_question, class_name: 'Question', inverse_of: :child_dependencies belongs_to :dependent_question, class_name: 'Question', inverse_of: :parent_dependencies - validates :parent_question, presence: true - validates :dependent_question, presence: true, - uniqueness: { scope: :parent_question_id } + validates :dependent_question, uniqueness: { scope: :parent_question_id } validate :same_exercise diff --git a/app/models/stem.rb b/app/models/stem.rb index b9ae8905..722eec8c 100644 --- a/app/models/stem.rb +++ b/app/models/stem.rb @@ -1,4 +1,4 @@ -class Stem < ActiveRecord::Base +class Stem < ApplicationRecord user_html :content stylable @@ -12,7 +12,6 @@ class Stem < ActiveRecord::Base has_many :combo_choices, dependent: :destroy validates :stylings, presence: true - validates :question, presence: true validates :content, presence: true end diff --git a/app/models/stem_answer.rb b/app/models/stem_answer.rb index 58c755fe..bcf0e5f9 100644 --- a/app/models/stem_answer.rb +++ b/app/models/stem_answer.rb @@ -1,10 +1,9 @@ -class StemAnswer < ActiveRecord::Base +class StemAnswer < ApplicationRecord belongs_to :stem belongs_to :answer - validates :stem, presence: true - validates :answer, presence: true, uniqueness: { scope: :stem_id } + validates :answer, uniqueness: { scope: :stem_id } validates :correctness, presence: true, numericality: { greater_than_or_equal_to: 0.0, less_than_or_equal_to: 1.0 } diff --git a/app/models/styling.rb b/app/models/styling.rb index ff947d81..3a3dae1c 100644 --- a/app/models/styling.rb +++ b/app/models/styling.rb @@ -1,8 +1,7 @@ -class Styling < ActiveRecord::Base +class Styling < ApplicationRecord belongs_to :stylable, polymorphic: true, inverse_of: :stylings - validates :stylable, presence: true validates :style, presence: true, inclusion: { in: Style.all }, uniqueness: { scope: [:stylable_type, :stylable_id] } diff --git a/app/models/tag.rb b/app/models/tag.rb index 1fdf3964..ab70975b 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -1,4 +1,4 @@ -class Tag < ActiveRecord::Base +class Tag < ApplicationRecord has_many :exercise_tags, dependent: :destroy has_many :vocab_term_tags, dependent: :destroy diff --git a/app/models/trusted_application.rb b/app/models/trusted_application.rb index 7934d137..6c3a1085 100644 --- a/app/models/trusted_application.rb +++ b/app/models/trusted_application.rb @@ -1,8 +1,8 @@ -class TrustedApplication < ActiveRecord::Base +class TrustedApplication < ApplicationRecord belongs_to :application, class_name: 'Doorkeeper::Application', inverse_of: :trusted_application - validates :application, presence: true, uniqueness: true + validates :application, uniqueness: true end diff --git a/app/models/user.rb b/app/models/user.rb index dd3d8122..b7406c6a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,4 @@ -class User < ActiveRecord::Base +class User < ApplicationRecord USERNAME_FORBIDDEN_CHAR_REGEX = /[^\w-]/ @@ -33,7 +33,7 @@ class User < ActiveRecord::Base has_many :sortings, dependent: :destroy - validates :account, presence: true, uniqueness: true + validates :account, uniqueness: true delegate :username, :first_name, :last_name, :full_name, :title, :name, :casual_name, :first_name=, :last_name=, :full_name=, diff --git a/app/models/vocab_distractor.rb b/app/models/vocab_distractor.rb index 51789ba9..4a6cb696 100644 --- a/app/models/vocab_distractor.rb +++ b/app/models/vocab_distractor.rb @@ -1,10 +1,9 @@ -class VocabDistractor < ActiveRecord::Base +class VocabDistractor < ApplicationRecord belongs_to :vocab_term, inverse_of: :vocab_distractors belongs_to :distractor_publication_group, class_name: 'PublicationGroup', inverse_of: :vocab_distractors - validates :vocab_term, presence: true - validates :distractor_publication_group, presence: true, uniqueness: { scope: :vocab_term_id } + validates :distractor_publication_group, uniqueness: { scope: :vocab_term_id } validates :distractor_term, presence: true validate :vocab_term_publication_group, :different_terms diff --git a/app/models/vocab_term.rb b/app/models/vocab_term.rb index 0ef599a6..22656d72 100644 --- a/app/models/vocab_term.rb +++ b/app/models/vocab_term.rb @@ -1,4 +1,4 @@ -class VocabTerm < ActiveRecord::Base +class VocabTerm < ApplicationRecord EQUALITY_ASSOCIATIONS = [ :tags, @@ -51,7 +51,7 @@ class VocabTerm < ActiveRecord::Base has_tags - has_many :vocab_distractors, dependent: :destroy + has_many :vocab_distractors, dependent: :destroy, autosave: true has_many :exercises, dependent: :destroy, autosave: true @@ -111,21 +111,20 @@ def before_publication errors.add(:base, 'must have at least 1 distractor') \ if distractor_literals.empty? && vocab_distractors.empty? - return false if errors.any? + throw(:abort) if errors.any? # Publish exercises latest_exercises.each do |exercise| exercise.publication.update_attribute :published_at, published_at end - true end def after_publication last_def = VocabTerm.joins(publication: :publication_group) .where(publication: {publication_group: {number: number}}) - .where {id != my{id}} - .order {publication.version.desc} + .where.not(id: id) + .order(Publication.arel_table[:version].desc) .limit(1) .pluck(:definition) return if definition == last_def diff --git a/app/models/vocab_term_tag.rb b/app/models/vocab_term_tag.rb index 58f9cfab..b0071f47 100644 --- a/app/models/vocab_term_tag.rb +++ b/app/models/vocab_term_tag.rb @@ -1,7 +1,6 @@ -class VocabTermTag < ActiveRecord::Base +class VocabTermTag < ApplicationRecord belongs_to :vocab_term belongs_to :tag - validates :vocab_term, presence: true - validates :tag, presence: true, uniqueness: { scope: :vocab_term_id } + validates :tag, uniqueness: { scope: :vocab_term_id } end diff --git a/app/representers/api/v1/exercises/representer.rb b/app/representers/api/v1/exercises/representer.rb index 61305cf4..20e3ceb3 100644 --- a/app/representers/api/v1/exercises/representer.rb +++ b/app/representers/api/v1/exercises/representer.rb @@ -67,7 +67,7 @@ def self.cache_key_types_for(represented, options = {}) end def self.cache_key_for(represented, type) - "#{represented.cache_key}/#{type}" + "#{represented.cache_key}/#{represented.cache_version}/#{type}" end def self.all_cache_keys_for(represented, options = {}) diff --git a/app/representers/api/v1/vocabs/term_with_distractors_and_exercise_ids_representer.rb b/app/representers/api/v1/vocabs/term_with_distractors_and_exercise_ids_representer.rb index 668946c8..bbbdcc03 100644 --- a/app/representers/api/v1/vocabs/term_with_distractors_and_exercise_ids_representer.rb +++ b/app/representers/api/v1/vocabs/term_with_distractors_and_exercise_ids_representer.rb @@ -53,7 +53,7 @@ def self.cache_key_types_for(represented, options = {}) end def self.cache_key_for(represented, type) - "#{represented.cache_key}/#{type}" + "#{represented.cache_key}/#{represented.cache_version}/#{type}" end def self.all_cache_keys_for(represented, options = {}) diff --git a/app/routines/exercises/import/old/row_importer.rb b/app/routines/exercises/import/old/row_importer.rb index 89731324..b9c4d675 100644 --- a/app/routines/exercises/import/old/row_importer.rb +++ b/app/routines/exercises/import/old/row_importer.rb @@ -17,7 +17,7 @@ def parse(text, exercise) return nil if text.blank? text = text.to_s - kd = Kramdown::Document.new(text.to_s.strip, attachable: exercise) + kd = Kramdown::Document.new(text.to_s.strip, math_engine: :openstax, attachable: exercise) # If only one

tag, remove it and just return the nodes below kd.root.children = kd.root.children.first.children \ if kd.root.children.length == 1 && kd.root.children.first.type == :p @@ -69,10 +69,10 @@ def perform_row_import(row, index) dok_tag, time_tag, display_type_tags, blooms_tag].flatten.uniq ex.tags = tags - latest_exercise = Exercise - .joins([{publication: :publication_group}, {exercise_tags: :tag}]) - .where(exercise_tags: {tag: {name: exercise_id_tag}}) - .order {[publication.publication_group.number.desc, publication.version.desc]}.first + pub = Publication.arel_table + pubg = PublicationGroup.arel_table + + latest_exercise = Exercise.joins([{publication: :publication_group}, {exercise_tags: :tag}]).where(exercise_tags: {tag: {name: exercise_id_tag}}).order([pubg[:number].desc, pub[:version].desc]).first unless latest_exercise.nil? ex.publication.publication_group = latest_exercise.publication.publication_group diff --git a/app/routines/exercises/import/quadbase.rb b/app/routines/exercises/import/quadbase.rb index a9e543f3..3427fb58 100644 --- a/app/routines/exercises/import/quadbase.rb +++ b/app/routines/exercises/import/quadbase.rb @@ -36,10 +36,12 @@ def import_question(hash) end id_tag = "exid:qb:#{hash['id']}" + pub = Publication.arel_table + pubg = PublicationGroup.arel_table latest_exercise = Exercise .joins([{publication: :publication_group}, {exercise_tags: :tag}]) .where(exercise_tags: {tag: {name: id_tag}}) - .order {[publication.publication_group.number.desc, publication.version.desc]}.first + .order(pubg[:number].desc, pub[:version].desc).first publication = import_metadata(exercise.publication, hash['attribution']) diff --git a/app/routines/search_exercises.rb b/app/routines/search_exercises.rb index a61c689d..f76e82b4 100644 --- a/app/routines/search_exercises.rb +++ b/app/routines/search_exercises.rb @@ -32,9 +32,20 @@ def exec(params = {}, options = {}) # this "latest_visible" condition is disabled. latest_visible = true + ex = Exercise.arel_table + qu = Question.arel_table + st = Stem.arel_table + ans = Answer.arel_table + pub = Publication.arel_table + pubg = PublicationGroup.arel_table + acct = OpenStax::Accounts::Account.arel_table + # NB encapsulates magic knowledge of how ActiveRecord will alias second join + acct_author = OpenStax::Accounts::Account.arel_table + acct_copyright = OpenStax::Accounts::Account.arel_table.alias('accounts_users') + run(:search, relation: relation, sortable_fields: SORTABLE_FIELDS, params: params) do |with| with.default_keyword :content - + with.keyword :id do |ids| ids.each do |id| sanitized_ids = to_number_array(id) @@ -61,25 +72,22 @@ def exec(params = {}, options = {}) elsif sanitized_versions.empty? @items = @items.where(publication_groups: { number: sanitized_numbers }) else - # Combine the id's one at a time using Squeel - @items = @items.where do - only_numbers = sanitized_uids.select { |suid| suid.second.blank? }.map(&:first) - only_versions = sanitized_uids.select { |suid| suid.first.blank? }.map(&:second) - full_uids = sanitized_uids.reject { |suid| suid.first.blank? || suid.second.blank? } - - cumulative_query = publication.publication_group.number.in(only_numbers) | - publication.version.in(only_versions) - - full_uids.each do |full_uid| - sanitized_number = full_uid.first - sanitized_version = full_uid.second - query = (publication.publication_group.number == sanitized_number) & - (publication.version == sanitized_version) - cumulative_query = cumulative_query | query + only_numbers = sanitized_uids.select { |suid| suid.second.blank? }.map(&:first) + only_versions = sanitized_uids.select { |suid| suid.first.blank? }.map(&:second) + full_uids = sanitized_uids.reject { |suid| suid.first.blank? || suid.second.blank? } + + cumulative_query = pubg[:number].in(only_numbers).or( + pub[:version].in(only_versions)) + + full_uids.each do |full_uid| + sanitized_number = full_uid.first + sanitized_version = full_uid.second + query = pubg[:number].eq(sanitized_number).and( + pub[:version].eq(sanitized_version)) + cumulative_query = cumulative_query.or(query) end - cumulative_query - end + @items = @items.where(cumulative_query) end end end @@ -149,7 +157,7 @@ def exec(params = {}, options = {}) sanitized_titles = to_string_array(ttl, append_wildcard: true, prepend_wildcard: true) next @items = @items.none if sanitized_titles.empty? - @items = @items.where { title.like_any sanitized_titles } + @items = @items.where(ex[:title].matches_any(sanitized_titles)) end end @@ -159,14 +167,12 @@ def exec(params = {}, options = {}) prepend_wildcard: true) next @items = @items.none if sanitized_contents.empty? - @items = @items.joins {[questions.outer.stems.outer, questions.outer.answers.outer]} - .where do - title.like_any(sanitized_contents) | - stimulus.like_any(sanitized_contents) | - questions.stimulus.like_any(sanitized_contents) | - questions.stems.content.like_any(sanitized_contents) | - questions.answers.content.like_any(sanitized_contents) - end + @items = @items.left_joins(questions: [:stems, :answers]).where( + ex[:title].matches_any(sanitized_contents) + .or(ex[:stimulus].matches_any(sanitized_contents)) + .or(qu[:stimulus].matches_any(sanitized_contents)) + .or(st[:content].matches_any(sanitized_contents)) + .or(ans[:content].matches_any(sanitized_contents))) end end @@ -175,12 +181,11 @@ def exec(params = {}, options = {}) sn = to_string_array(name, append_wildcard: true) next @items = @items.none if sn.empty? - @items = @items.joins(publication: { authors: { user: :account } }).where do - openstax_accounts_accounts.username.like_any(sn) | - openstax_accounts_accounts.first_name.like_any(sn) | - openstax_accounts_accounts.last_name.like_any(sn) | - openstax_accounts_accounts.full_name.like_any(sn) - end + @items = @items.joins(publication: { authors: { user: :account } }).where( + acct[:username].matches_any(sn) + .or(acct[:first_name].matches_any(sn)) + .or(acct[:last_name].matches_any(sn)) + .or(acct[:full_name].matches_any(sn))) end end @@ -189,12 +194,11 @@ def exec(params = {}, options = {}) sn = to_string_array(name, append_wildcard: true) next @items = @items.none if sn.empty? - @items = @items.joins(publication: { copyright_holders: { user: :account } }).where do - openstax_accounts_accounts.username.like_any(sn) | - openstax_accounts_accounts.first_name.like_any(sn) | - openstax_accounts_accounts.last_name.like_any(sn) | - openstax_accounts_accounts.full_name.like_any(sn) - end + @items = @items.joins(publication: { copyright_holders: { user: :account } }).where( + acct[:username].matches_any(sn) + .or(acct[:first_name].matches_any(sn)) + .or(acct[:last_name].matches_any(sn)) + .or(acct[:full_name].matches_any(sn))) end end @@ -203,38 +207,33 @@ def exec(params = {}, options = {}) sn = to_string_array(name, append_wildcard: true) next @items = @items.none if sn.empty? - @items = @items.joins {publication.authors.outer.user.outer.account.outer} - .joins {publication.copyright_holders.outer.user.outer.account.outer} - .where do - publication.authors.user.account.username.like_any(sn) | - publication.authors.user.account.first_name.like_any(sn) | - publication.authors.user.account.last_name.like_any(sn) | - publication.authors.user.account.full_name.like_any(sn) | - publication.copyright_holders.user.account.username.like_any(sn) | - publication.copyright_holders.user.account.first_name.like_any(sn) | - publication.copyright_holders.user.account.last_name.like_any(sn) | - publication.copyright_holders.user.account.full_name.like_any(sn) - end + @items = @items.joins(publication: { authors: { user: :account } }) + .joins(publication: { copyright_holders: { user: :account } }).where( + acct_author[:username].matches_any(sn) + .or(acct_author[:first_name].matches_any(sn)) + .or(acct_author[:last_name].matches_any(sn)) + .or(acct_author[:full_name].matches_any(sn)) + .or(acct_copyright[:username].matches_any(sn)) + .or(acct_copyright[:first_name].matches_any(sn)) + .or(acct_copyright[:last_name].matches_any(sn)) + .or(acct_copyright[:full_name].matches_any(sn))) end end end - pg = PublicationGroup.arel_table - pb = Publication.arel_table - outputs.items = outputs.items.select( [ - Exercise.arel_table[ Arel.star ], - pg[:uuid], - pg[:number], - pb[:version], - pb[:published_at] + ex[ Arel.star ], + pubg[:uuid], + pubg[:number], + pub[:version], + pub[:published_at] ] ).distinct return unless latest_visible outputs.items = outputs.items.chainable_latest - outputs.total_count = outputs.items.limit(nil).offset(nil).reorder(nil).count + outputs.total_count = outputs.items.limit(nil).offset(nil).reorder(nil).count(:all) end end diff --git a/app/routines/search_vocab_terms.rb b/app/routines/search_vocab_terms.rb index ae9449b4..60907d6b 100644 --- a/app/routines/search_vocab_terms.rb +++ b/app/routines/search_vocab_terms.rb @@ -33,14 +33,24 @@ def exec(params = {}, options = {}) # this "latest_visible" condition is disabled. latest_visible = true + vt = VocabTerm.arel_table + pubg = PublicationGroup.arel_table + pub = Publication.arel_table + acct = OpenStax::Accounts::Account.arel_table + # NB: this encapsulates magic knowledge of how ActiveRecord will alias the second join of accounts + acct_author = OpenStax::Accounts::Account.arel_table + acct_copyright = OpenStax::Accounts::Account.arel_table.alias('accounts_users') + + run(:search, relation: relation, sortable_fields: SORTABLE_FIELDS, params: params) do |with| # Block to be used for searches by name or term + name_search_block = lambda do |names| names.each do |nm| sanitized_names = to_string_array(nm, append_wildcard: true, prepend_wildcard: true) next @items = @items.none if sanitized_names.empty? - @items = @items.where { name.like_any sanitized_names } + @items = @items.where( vt[:name].matches_any(sanitized_names )) end end @@ -72,25 +82,22 @@ def exec(params = {}, options = {}) elsif sanitized_versions.empty? @items = @items.where(publication_groups: { number: sanitized_numbers }) else - # Combine the id's one at a time using Squeel - @items = @items.where do - only_numbers = sanitized_uids.select { |suid| suid.second.blank? }.map(&:first) - only_versions = sanitized_uids.select { |suid| suid.first.blank? }.map(&:second) - full_uids = sanitized_uids.reject { |suid| suid.first.blank? || suid.second.blank? } - - cumulative_query = publication.publication_group.number.in(only_numbers) | - publication.version.in(only_versions) - - full_uids.each do |full_uid| - sanitized_number = full_uid.first - sanitized_version = full_uid.second - query = (publication.publication_group.number == sanitized_number) & - (publication.version == sanitized_version) - cumulative_query = cumulative_query | query + only_numbers = sanitized_uids.select { |suid| suid.second.blank? }.map(&:first) + only_versions = sanitized_uids.select { |suid| suid.first.blank? }.map(&:second) + full_uids = sanitized_uids.reject { |suid| suid.first.blank? || suid.second.blank? } + + cumulative_query = pubg[:number].in(only_numbers).or( + pub[:version].in(only_versions)) + + full_uids.each do |full_uid| + sanitized_number = full_uid.first + sanitized_version = full_uid.second + query = pubg[:number].eq(sanitized_number).and( + pub[:version].eq(sanitized_version)) + cumulative_query = cumulative_query.or(query) end - cumulative_query - end + @items = @items.where(cumulative_query) end end end @@ -164,7 +171,7 @@ def exec(params = {}, options = {}) sanitized_definitions = to_string_array(df, append_wildcard: true, prepend_wildcard: true) next @items = @items.none if sanitized_definitions.empty? - @items = @items.where { definition.like_any sanitized_definitions } + @items = @items.where( vt[:definition].matches_any(sanitized_definitions) ) end end @@ -174,9 +181,8 @@ def exec(params = {}, options = {}) prepend_wildcard: true) next @items = @items.none if sanitized_contents.empty? - @items = @items.where do - name.like_any(sanitized_contents) | definition.like_any(sanitized_contents) - end + @items = @items.where(vt[:name].matches_any(sanitized_contents).or( + vt[:definition].matches_any(sanitized_contents))) end end @@ -185,12 +191,11 @@ def exec(params = {}, options = {}) sn = to_string_array(name, append_wildcard: true) next @items = @items.none if sn.empty? - @items = @items.joins(publication: { authors: { user: :account } }).where do - openstax_accounts_accounts.username.like_any(sn) | - openstax_accounts_accounts.first_name.like_any(sn) | - openstax_accounts_accounts.last_name.like_any(sn) | - openstax_accounts_accounts.full_name.like_any(sn) - end + @items = @items.joins(publication: { authors: { user: :account } }).where( + acct[:username].matches_any(sn) + .or(acct[:first_name].matches_any(sn)) + .or(acct[:last_name].matches_any(sn)) + .or(acct[:full_name].matches_any(sn))) end end @@ -199,12 +204,11 @@ def exec(params = {}, options = {}) sn = to_string_array(name, append_wildcard: true) next @items = @items.none if sn.empty? - @items = @items.joins(publication: { copyright_holders: { user: :account } }).where do - openstax_accounts_accounts.username.like_any(sn) | - openstax_accounts_accounts.first_name.like_any(sn) | - openstax_accounts_accounts.last_name.like_any(sn) | - openstax_accounts_accounts.full_name.like_any(sn) - end + @items = @items.joins(publication: { copyright_holders: { user: :account } }).where( + acct[:username].matches_any(sn) + .or(acct[:first_name].matches_any(sn)) + .or(acct[:last_name].matches_any(sn)) + .or(acct[:full_name].matches_any(sn))) end end @@ -213,38 +217,33 @@ def exec(params = {}, options = {}) sn = to_string_array(name, append_wildcard: true) next @items = @items.none if sn.empty? - @items = @items.joins {publication.authors.outer.user.outer.account.outer} - .joins {publication.copyright_holders.outer.user.outer.account.outer} - .where do - publication.authors.user.account.username.like_any(sn) | - publication.authors.user.account.first_name.like_any(sn) | - publication.authors.user.account.last_name.like_any(sn) | - publication.authors.user.account.full_name.like_any(sn) | - publication.copyright_holders.user.account.username.like_any(sn) | - publication.copyright_holders.user.account.first_name.like_any(sn) | - publication.copyright_holders.user.account.last_name.like_any(sn) | - publication.copyright_holders.user.account.full_name.like_any(sn) - end + @items = @items.joins(publication: { authors: { user: :account } }) + .joins(publication: { copyright_holders: { user: :account } }).where( + acct_author[:username].matches_any(sn) + .or(acct_author[:first_name].matches_any(sn)) + .or(acct_author[:last_name].matches_any(sn)) + .or(acct_author[:full_name].matches_any(sn)) + .or(acct_copyright[:username].matches_any(sn)) + .or(acct_copyright[:first_name].matches_any(sn)) + .or(acct_copyright[:last_name].matches_any(sn)) + .or(acct_copyright[:full_name].matches_any(sn))) end end end - pg = PublicationGroup.arel_table - pb = Publication.arel_table - outputs.items = outputs.items.select( [ - VocabTerm.arel_table[ Arel.star ], - pg[:uuid], - pg[:number], - pb[:version], - pb[:published_at] + vt[ Arel.star ], + pubg[:uuid], + pubg[:number], + pub[:version], + pub[:published_at] ] ).distinct return unless latest_visible outputs.items = outputs.items.chainable_latest - outputs.total_count = outputs.items.limit(nil).offset(nil).reorder(nil).count + outputs.total_count = outputs.items.limit(nil).offset(nil).reorder(nil).count(:all) end end diff --git a/app/views/admin/console/_misc.html.erb b/app/views/admin/console/_misc.html.erb index 02bb22b4..1b036575 100644 --- a/app/views/admin/console/_misc.html.erb +++ b/app/views/admin/console/_misc.html.erb @@ -7,8 +7,6 @@

  • <%= link_to 'ActionController::RoutingError', admin_exception_url('ActionController::RoutingError', args: '/blah/blah/blah'.inspect) %>
  • -
  • <%= link_to 'ActionController::UnknownController', - admin_exception_url('ActionController::UnknownController') %>
  • <%= link_to 'AbstractController::ActionNotFound', admin_exception_url('AbstractController::ActionNotFound') %>
  • <%= link_to 'ActionView::MissingTemplate', diff --git a/bin/bundle b/bin/bundle index 524dfd3f..f19acf5b 100755 --- a/bin/bundle +++ b/bin/bundle @@ -1,105 +1,3 @@ #!/usr/bin/env ruby -# frozen_string_literal: true - -# -# This file was generated by Bundler. -# -# The application 'bundle' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require "rubygems" - -m = Module.new do - module_function - - def invoked_as_script? - File.expand_path($0) == File.expand_path(__FILE__) - end - - def env_var_version - ENV["BUNDLER_VERSION"] - end - - def cli_arg_version - return unless invoked_as_script? # don't want to hijack other binstubs - return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` - bundler_version = nil - update_index = nil - ARGV.each_with_index do |a, i| - if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN - bundler_version = a - end - next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ - bundler_version = $1 || ">= 0.a" - update_index = i - end - bundler_version - end - - def gemfile - gemfile = ENV["BUNDLE_GEMFILE"] - return gemfile if gemfile && !gemfile.empty? - - File.expand_path("../../Gemfile", __FILE__) - end - - def lockfile - lockfile = - case File.basename(gemfile) - when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) - else "#{gemfile}.lock" - end - File.expand_path(lockfile) - end - - def lockfile_version - return unless File.file?(lockfile) - lockfile_contents = File.read(lockfile) - return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ - Regexp.last_match(1) - end - - def bundler_version - @bundler_version ||= begin - env_var_version || cli_arg_version || - lockfile_version || "#{Gem::Requirement.default}.a" - end - end - - def load_bundler! - ENV["BUNDLE_GEMFILE"] ||= gemfile - - # must dup string for RG < 1.8 compatibility - activate_bundler(bundler_version.dup) - end - - def activate_bundler(bundler_version) - if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0") - bundler_version = "< 2" - end - gem_error = activation_error_handling do - gem "bundler", bundler_version - end - return if gem_error.nil? - require_error = activation_error_handling do - require "bundler/version" - end - return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION)) - warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`" - exit 42 - end - - def activation_error_handling - yield - nil - rescue StandardError, LoadError => e - e - end -end - -m.load_bundler! - -if m.invoked_as_script? - load Gem.bin_path("bundler", "bundle") -end +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rails b/bin/rails index 5191e692..07396602 100755 --- a/bin/rails +++ b/bin/rails @@ -1,4 +1,4 @@ #!/usr/bin/env ruby -APP_PATH = File.expand_path('../../config/application', __FILE__) +APP_PATH = File.expand_path('../config/application', __dir__) require_relative '../config/boot' require 'rails/commands' diff --git a/bin/setup b/bin/setup index acdb2c13..94fd4d79 100755 --- a/bin/setup +++ b/bin/setup @@ -1,29 +1,36 @@ #!/usr/bin/env ruby -require 'pathname' +require 'fileutils' +include FileUtils # path to your application root. -APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) +APP_ROOT = File.expand_path('..', __dir__) -Dir.chdir APP_ROOT do +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: + # Add necessary setup steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') - puts "== Installing dependencies ==" - system "gem install bundler --conservative" - system "bundle check || bundle install" + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') # puts "\n== Copying sample files ==" - # unless File.exist?("config/database.yml") - # system "cp config/database.yml.sample config/database.yml" + # unless File.exist?('config/database.yml') + # cp 'config/database.yml.sample', 'config/database.yml' # end puts "\n== Preparing database ==" - system "bin/rake db:setup" + system! 'bin/rails db:setup' puts "\n== Removing old logs and tempfiles ==" - system "rm -f log/*" - system "rm -rf tmp/cache" + system! 'bin/rails log:clear tmp:clear' puts "\n== Restarting application server ==" - system "touch tmp/restart.txt" + system! 'bin/rails restart' end diff --git a/config/application.rb b/config/application.rb index 6e43167c..6e962cea 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,4 +1,4 @@ -require File.expand_path('../boot', __FILE__) +require_relative 'boot' require 'rails/all' @@ -11,6 +11,9 @@ module Exercises class Application < Rails::Application + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 5.2 + # 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. @@ -24,18 +27,17 @@ class Application < Rails::Application # config.i18n.default_locale = :de ActiveSupport.escape_html_entities_in_json = false - config.active_record.raise_in_transactional_callbacks = true - # Set the default cache store to Redis # This setting cannot be set from an initializer # See https://github.com/rails/rails/issues/10908 - redis_secrets = secrets['redis'] + redis_secrets = secrets[:redis] config.cache_store = :redis_store, { - url: redis_secrets['url'], - namespace: redis_secrets['namespaces']['cache'], + url: redis_secrets[:url], + namespace: redis_secrets[:namespaces][:cache], expires_in: 1.day, compress: true, compress_threshold: 1.kilobyte } + end end diff --git a/config/boot.rb b/config/boot.rb index 5e5f0c1f..b9e460ce 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,4 +1,4 @@ -# Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) -require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) +require 'bundler/setup' # Set up gems listed in the Gemfile. +require 'bootsnap/setup' # Speed up boot time by caching expensive operations. diff --git a/config/cable.yml b/config/cable.yml new file mode 100644 index 00000000..1ac654de --- /dev/null +++ b/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> + channel_prefix: exercises_production diff --git a/config/database.yml b/config/database.yml index 9affc495..7d042d23 100644 --- a/config/database.yml +++ b/config/database.yml @@ -14,6 +14,7 @@ test: <<: *default database: '<%= ENV['OXE_TEST_DB'] || 'ox_exercises_test' %><%= \ "_#{ENV['TEST_ENV_NUMBER']}" if !ENV['TEST_ENV_NUMBER'].blank? %>' + reaping_frequency: 0 # 0 = disabled - incompatible with our DatabaseCleaner config production: <<: *default diff --git a/config/environment.rb b/config/environment.rb index 31714ec5..ee1e514b 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,5 +1,5 @@ -# Load the rails application -require File.expand_path('../application', __FILE__) +# Load the Rails application. +require_relative 'application' require 'scout_helper' @@ -26,10 +26,10 @@ require 'ar_collection_setter' -require 'active_record/calculations_patch' +require 'active_record/table_association_name_patch' SITE_NAME = "OpenStax Exercises" COPYRIGHT_HOLDER = "Rice University" -# Initialize the rails application +# Initialize the Rails application Exercises::Application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb index 3fe13011..4f313077 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -13,15 +13,22 @@ config.consider_all_requests_local = true config.action_controller.perform_caching = false + config.cache_store = :null_store + # 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 + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + # Debug mode disables concatenation and preprocessing of assets. # This option may cause significant delays in view rendering with a large # number of complex assets. diff --git a/config/environments/test.rb b/config/environments/test.rb index 37f4d138..af95530b 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -12,9 +12,11 @@ # preloads Rails for running tests, you may have to set it to true. config.eager_load = false - # Configure static asset server for tests with Cache-Control for performance. - config.serve_static_files = true - config.static_cache_control = 'public, max-age=3600' + # 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=#{1.hour.seconds.to_i}" + } # Show full error reports and disable caching. config.consider_all_requests_local = true @@ -25,6 +27,7 @@ # 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 diff --git a/config/initializers/a15k.rb b/config/initializers/a15k.rb index 5ced0505..1301766d 100644 --- a/config/initializers/a15k.rb +++ b/config/initializers/a15k.rb @@ -1,7 +1,7 @@ -secrets = Rails.application.secrets['a15k'] +secrets = Rails.application.secrets[:a15k] A15kClient.configure do |c| - c.scheme = secrets['scheme'] - c.host = secrets['host'] - c.api_key['Authorization'] = secrets['access_token'] + c.scheme = secrets[:scheme] + c.host = secrets[:host] + c.api_key['Authorization'] = secrets[:access_token] end unless secrets.nil? diff --git a/config/initializers/amazon_ses.rb b/config/initializers/amazon_ses.rb index 2a04fde2..9781ccae 100644 --- a/config/initializers/amazon_ses.rb +++ b/config/initializers/amazon_ses.rb @@ -1,11 +1,11 @@ if Rails.env.production? - secrets = Rails.application.secrets['aws']['ses'] + secrets = Rails.application.secrets[:aws][:ses] ActionMailer::Base.add_delivery_method( :ses, AWS::SES::Base, - access_key_id: secrets['access_key_id'], - secret_access_key: secrets['secret_access_key'], - server: secrets['endpoint_server'] + access_key_id: secrets[:access_key_id], + secret_access_key: secrets[:secret_access_key], + server: secrets[:endpoint_server] ) end diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb new file mode 100644 index 00000000..89d2efab --- /dev/null +++ b/config/initializers/application_controller_renderer.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +# ActiveSupport::Reloader.to_prepare do +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) +# end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 383a47b1..802465c5 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -3,6 +3,11 @@ # 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 +# Add Yarn node_modules folder to the asset load path. +Rails.application.config.assets.paths << Rails.root.join('node_modules') + # 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/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb index c7656acb..145199b0 100644 --- a/config/initializers/carrierwave.rb +++ b/config/initializers/carrierwave.rb @@ -6,24 +6,24 @@ # Upload to AWS only in the production environment config.storage = if Rails.env.production? - secrets = Rails.application.secrets['aws']['s3'] + secrets = Rails.application.secrets[:aws][:s3] - config.asset_host = secrets['asset_host'] + config.asset_host = secrets[:asset_host] config.fog_attributes = { 'Cache-Control' => 'max-age=31536000' } - config.fog_directory = secrets['bucket_name'] + config.fog_directory = secrets[:bucket_name] config.fog_provider = 'fog/aws' - fog_credentials = secrets['access_key_id'].blank? ? \ + fog_credentials = secrets[:access_key_id].blank? ? \ { use_iam_profile: true } : \ - { aws_access_key_id: secrets['access_key_id'], - aws_secret_access_key: secrets['secret_access_key'] } + { aws_access_key_id: secrets[:access_key_id], + aws_secret_access_key: secrets[:secret_access_key] } config.fog_credentials = fog_credentials.merge( provider: 'AWS', - region: secrets['region'], - endpoint: secrets['endpoint_server'] + region: secrets[:region], + endpoint: secrets[:endpoint_server] ) :fog diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb new file mode 100644 index 00000000..d3bcaa5e --- /dev/null +++ b/config/initializers/content_security_policy.rb @@ -0,0 +1,25 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy +# For further information see the following documentation +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy + +# Rails.application.config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https + +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end + +# If you are using UJS then enable automatic nonce generation +# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } + +# Report CSP violations to a specified URI +# For further information see the following documentation: +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only +# Rails.application.config.content_security_policy_report_only = true diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb index 7a06a89f..5a6a32d3 100644 --- a/config/initializers/cookies_serializer.rb +++ b/config/initializers/cookies_serializer.rb @@ -1,3 +1,5 @@ # Be sure to restart your server when you modify this file. -Rails.application.config.action_dispatch.cookies_serializer = :json \ No newline at end of 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/config/initializers/kramdown.rb b/config/initializers/kramdown.rb index e89c60ef..b6d06c00 100644 --- a/config/initializers/kramdown.rb +++ b/config/initializers/kramdown.rb @@ -12,7 +12,8 @@ def add_link_with_attachments(el, href, title, alt_text = nil, ial = nil) add_link_without_attachments(el, href, title, alt_text, ial) end - alias_method_chain :add_link, :attachments + alias_method :add_link_without_attachments, :add_link + alias_method :add_link, :add_link_with_attachments SINGLE_DOLLAR_INLINE_MATH_START = /(?" : el.value) - text.gsub!(/<\/?script>?/, '') + # This just wraps the LaTeX in a div or span w/ data-math attr + module OpenStax - preview = preview_string(converter, el, opts) + def self.call(converter, el, opts) + type = el.options[:category] + text = (el.value =~ /<|&/ ? "% " : el.value) + text.gsub!(/<\/?script>?/, '') + + preview = preview_string(converter, el, opts) + + attr = {:'data-math' => text} + if type == :block + preview << converter.format_as_block_html('div', attr, text, opts[:indent]) + else + preview << converter.format_as_span_html('span', attr, text) + end + end + + # Copied from MathJax math_engine + def self.preview_string(converter, el, opts) + preview = converter.options[:math_engine_opts][:preview] + return '' unless preview + + preview = (preview == true ? converter.escape_html(el.value) : preview.to_s) + + preview_as_code = converter.options[:math_engine_opts][:preview_as_code] + + if el.options[:category] == :block + if preview_as_code + converter.format_as_block_html('pre', {'class' => 'MathJax_Preview'}, + converter.format_as_span_html('code', {}, preview), + opts[:indent]) + else + converter.format_as_block_html('div', {'class' => 'MathJax_Preview'}, preview, + opts[:indent]) + end + else + converter.format_as_span_html(preview_as_code ? 'code' : 'span', + {'class' => 'MathJax_Preview'}, preview) + end + end - attr = {:'data-math' => text} - if type == :block - preview << converter.format_as_block_html('div', attr, text, opts[:indent]) - else - preview << converter.format_as_span_html('span', attr, text) end + end + add_math_engine(:openstax, MathEngine::OpenStax) + end diff --git a/config/initializers/openstax_accounts.rb b/config/initializers/openstax_accounts.rb index 32576722..17222adc 100644 --- a/config/initializers/openstax_accounts.rb +++ b/config/initializers/openstax_accounts.rb @@ -1,14 +1,14 @@ require 'user_mapper' -secrets = Rails.application.secrets['openstax']['accounts'] +secrets = Rails.application.secrets[:openstax][:accounts] # By default, stub unless in the production environment -stub = secrets['stub'].nil? ? !Rails.env.production? : secrets['stub'] +stub = secrets[:stub].nil? ? !Rails.env.production? : secrets[:stub] OpenStax::Accounts.configure do |config| - config.openstax_application_id = secrets['client_id'] - config.openstax_application_secret = secrets['secret'] - config.openstax_accounts_url = secrets['url'] + config.openstax_application_id = secrets[:client_id] + config.openstax_application_secret = secrets[:secret] + config.openstax_accounts_url = secrets[:url] config.enable_stubbing = stub config.logout_via = :delete config.account_user_mapper = UserMapper diff --git a/config/initializers/rescue_from.rb b/config/initializers/rescue_from.rb index 79ec6f34..c88aed4c 100644 --- a/config/initializers/rescue_from.rb +++ b/config/initializers/rescue_from.rb @@ -6,7 +6,7 @@ config.raise_exceptions = Rails.application.config.consider_all_requests_local config.app_name = 'Exercises' - config.contact_name = exception_secrets['contact_name'] + config.contact_name = exception_secrets[:contact_name] # Notify devs using sentry-raven config.notify_proc = ->(proxy, controller) do diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index 33725e95..bbfc3961 100644 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -5,10 +5,10 @@ # 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] if respond_to?(:wrap_parameters) + 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 +# self.include_root_in_json = true # end diff --git a/config/locales/en.yml b/config/locales/en.yml index 179c14ca..decc5a85 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,5 +1,33 @@ -# Sample localization file for English. Add more files in this directory for other locales. -# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. +# 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. +# +# The following keys must be escaped otherwise they will not be retrieved by +# the default I18n backend: +# +# true, false, on, off, yes, no +# +# Instead, surround them with single quotes. +# +# en: +# 'true': 'foo' +# +# To learn more, please read the Rails Internationalization guide +# available at http://guides.rubyonrails.org/i18n.html. en: hello: "Hello world" diff --git a/config/puma.rb b/config/puma.rb new file mode 100644 index 00000000..1e19380d --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,56 @@ +# 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 } +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! + +# If you are preloading your application and using Active Record, it's +# recommended that you close any connections to the database before workers +# are forked to prevent connection leakage. +# +# before_fork do +# ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord) +# end + +# 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 the `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, as 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/config/spring.rb b/config/spring.rb new file mode 100644 index 00000000..c9119b40 --- /dev/null +++ b/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/config/storage.yml b/config/storage.yml new file mode 100644 index 00000000..d32f76e8 --- /dev/null +++ b/config/storage.yml @@ -0,0 +1,34 @@ +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %> + +# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +# amazon: +# service: S3 +# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> +# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> +# region: us-east-1 +# bucket: your_own_bucket + +# Remember not to checkin your GCS keyfile to a repository +# google: +# service: GCS +# project: your_project +# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> +# bucket: your_own_bucket + +# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) +# microsoft: +# service: AzureStorage +# storage_account_name: your_account_name +# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> +# container: your_container_name + +# mirror: +# service: Mirror +# primary: local +# mirrors: [ amazon, google, microsoft ] diff --git a/db/migrate/20140724183731_create_doorkeeper_tables.rb b/db/migrate/20140724183731_create_doorkeeper_tables.rb index af5aa7d8..37ecbe7b 100644 --- a/db/migrate/20140724183731_create_doorkeeper_tables.rb +++ b/db/migrate/20140724183731_create_doorkeeper_tables.rb @@ -1,4 +1,4 @@ -class CreateDoorkeeperTables < ActiveRecord::Migration +class CreateDoorkeeperTables < ActiveRecord::Migration[4.2] def change create_table :oauth_applications do |t| t.string :name, null: false diff --git a/db/migrate/20140724183732_add_owner_to_application.rb b/db/migrate/20140724183732_add_owner_to_application.rb index fc85092e..e290472a 100644 --- a/db/migrate/20140724183732_add_owner_to_application.rb +++ b/db/migrate/20140724183732_add_owner_to_application.rb @@ -1,4 +1,4 @@ -class AddOwnerToApplication < ActiveRecord::Migration +class AddOwnerToApplication < ActiveRecord::Migration[4.2] def change add_column :oauth_applications, :owner_id, :integer add_column :oauth_applications, :owner_type, :string diff --git a/db/migrate/20140724183745_acts_as_votable_migration.rb b/db/migrate/20140724183745_acts_as_votable_migration.rb index 4bdcbe37..2516d700 100644 --- a/db/migrate/20140724183745_acts_as_votable_migration.rb +++ b/db/migrate/20140724183745_acts_as_votable_migration.rb @@ -1,4 +1,4 @@ -class ActsAsVotableMigration < ActiveRecord::Migration +class ActsAsVotableMigration < ActiveRecord::Migration[4.2] def self.up create_table :votes do |t| diff --git a/db/migrate/20140724183919_install_commontator.rb b/db/migrate/20140724183919_install_commontator.rb index 3b93792a..a4df0822 100644 --- a/db/migrate/20140724183919_install_commontator.rb +++ b/db/migrate/20140724183919_install_commontator.rb @@ -1,5 +1,5 @@ # This migration comes from commontator (originally 0) -class InstallCommontator < ActiveRecord::Migration +class InstallCommontator < ActiveRecord::Migration[4.2] def change create_table :commontator_comments do |t| t.string :creator_type diff --git a/db/migrate/20140724183932_install_fine_print.rb b/db/migrate/20140724183932_install_fine_print.rb index 5c3c5e27..0517ba68 100644 --- a/db/migrate/20140724183932_install_fine_print.rb +++ b/db/migrate/20140724183932_install_fine_print.rb @@ -1,5 +1,5 @@ # This migration comes from fine_print (originally 0) -class InstallFinePrint < ActiveRecord::Migration +class InstallFinePrint < ActiveRecord::Migration[4.2] def change create_table :fine_print_contracts do |t| t.string :name, :null => false diff --git a/db/migrate/20140724184012_create_openstax_accounts_accounts.rb b/db/migrate/20140724184012_create_openstax_accounts_accounts.rb index ccbd5ce8..540285e0 100644 --- a/db/migrate/20140724184012_create_openstax_accounts_accounts.rb +++ b/db/migrate/20140724184012_create_openstax_accounts_accounts.rb @@ -1,5 +1,5 @@ # This migration comes from openstax_accounts (originally 0) -class CreateOpenStaxAccountsAccounts < ActiveRecord::Migration +class CreateOpenStaxAccountsAccounts < ActiveRecord::Migration[4.2] def change create_table :openstax_accounts_accounts do |t| t.integer :openstax_uid, :null => false diff --git a/db/migrate/20140724184013_create_openstax_accounts_groups.openstax_accounts.rb b/db/migrate/20140724184013_create_openstax_accounts_groups.openstax_accounts.rb index 6f7deca2..629f1cee 100644 --- a/db/migrate/20140724184013_create_openstax_accounts_groups.openstax_accounts.rb +++ b/db/migrate/20140724184013_create_openstax_accounts_groups.openstax_accounts.rb @@ -1,5 +1,5 @@ # This migration comes from openstax_accounts (originally 1) -class CreateOpenStaxAccountsGroups < ActiveRecord::Migration +class CreateOpenStaxAccountsGroups < ActiveRecord::Migration[4.2] def change create_table :openstax_accounts_groups do |t| t.integer :openstax_uid, :null => false diff --git a/db/migrate/20140724184014_create_openstax_accounts_group_members.openstax_accounts.rb b/db/migrate/20140724184014_create_openstax_accounts_group_members.openstax_accounts.rb index e563986b..c55ad8eb 100644 --- a/db/migrate/20140724184014_create_openstax_accounts_group_members.openstax_accounts.rb +++ b/db/migrate/20140724184014_create_openstax_accounts_group_members.openstax_accounts.rb @@ -1,5 +1,5 @@ # This migration comes from openstax_accounts (originally 2) -class CreateOpenStaxAccountsGroupMembers < ActiveRecord::Migration +class CreateOpenStaxAccountsGroupMembers < ActiveRecord::Migration[4.2] def change create_table :openstax_accounts_group_members do |t| t.references :group, null: false diff --git a/db/migrate/20140724184015_create_openstax_accounts_group_owners.openstax_accounts.rb b/db/migrate/20140724184015_create_openstax_accounts_group_owners.openstax_accounts.rb index 6b47e522..66782e92 100644 --- a/db/migrate/20140724184015_create_openstax_accounts_group_owners.openstax_accounts.rb +++ b/db/migrate/20140724184015_create_openstax_accounts_group_owners.openstax_accounts.rb @@ -1,5 +1,5 @@ # This migration comes from openstax_accounts (originally 3) -class CreateOpenStaxAccountsGroupOwners < ActiveRecord::Migration +class CreateOpenStaxAccountsGroupOwners < ActiveRecord::Migration[4.2] def change create_table :openstax_accounts_group_owners do |t| t.references :group, null: false diff --git a/db/migrate/20140724184016_create_openstax_accounts_group_nestings.openstax_accounts.rb b/db/migrate/20140724184016_create_openstax_accounts_group_nestings.openstax_accounts.rb index bf8d4b1a..bf1b5f57 100644 --- a/db/migrate/20140724184016_create_openstax_accounts_group_nestings.openstax_accounts.rb +++ b/db/migrate/20140724184016_create_openstax_accounts_group_nestings.openstax_accounts.rb @@ -1,5 +1,5 @@ # This migration comes from openstax_accounts (originally 4) -class CreateOpenStaxAccountsGroupNestings < ActiveRecord::Migration +class CreateOpenStaxAccountsGroupNestings < ActiveRecord::Migration[4.2] def change create_table :openstax_accounts_group_nestings do |t| t.references :member_group, null: false diff --git a/db/migrate/20140724184630_create_users.rb b/db/migrate/20140724184630_create_users.rb index 22716422..efb35f7a 100644 --- a/db/migrate/20140724184630_create_users.rb +++ b/db/migrate/20140724184630_create_users.rb @@ -1,4 +1,4 @@ -class CreateUsers < ActiveRecord::Migration +class CreateUsers < ActiveRecord::Migration[4.2] def change create_table :users do |t| t.references :account, null: false diff --git a/db/migrate/20140724184800_create_administrators.rb b/db/migrate/20140724184800_create_administrators.rb index 00d5b5ea..e29a7e95 100644 --- a/db/migrate/20140724184800_create_administrators.rb +++ b/db/migrate/20140724184800_create_administrators.rb @@ -1,4 +1,4 @@ -class CreateAdministrators < ActiveRecord::Migration +class CreateAdministrators < ActiveRecord::Migration[4.2] def change create_table :administrators do |t| t.references :user, null: false diff --git a/db/migrate/20140724184944_create_exercises.rb b/db/migrate/20140724184944_create_exercises.rb index 932df6f6..c6050cc2 100644 --- a/db/migrate/20140724184944_create_exercises.rb +++ b/db/migrate/20140724184944_create_exercises.rb @@ -1,4 +1,4 @@ -class CreateExercises < ActiveRecord::Migration +class CreateExercises < ActiveRecord::Migration[4.2] def change create_table :exercises do |t| t.string :title diff --git a/db/migrate/20140724185123_create_questions.rb b/db/migrate/20140724185123_create_questions.rb index 86a85337..f2ccbad5 100644 --- a/db/migrate/20140724185123_create_questions.rb +++ b/db/migrate/20140724185123_create_questions.rb @@ -1,4 +1,4 @@ -class CreateQuestions < ActiveRecord::Migration +class CreateQuestions < ActiveRecord::Migration[4.2] def change create_table :questions do |t| t.references :exercise, null: false diff --git a/db/migrate/20140724185227_create_stems.rb b/db/migrate/20140724185227_create_stems.rb index 82140edb..787d774f 100644 --- a/db/migrate/20140724185227_create_stems.rb +++ b/db/migrate/20140724185227_create_stems.rb @@ -1,4 +1,4 @@ -class CreateStems < ActiveRecord::Migration +class CreateStems < ActiveRecord::Migration[4.2] def change create_table :stems do |t| t.references :question, null: false diff --git a/db/migrate/20140724203302_create_stylings.rb b/db/migrate/20140724203302_create_stylings.rb index a37ea973..05a09951 100644 --- a/db/migrate/20140724203302_create_stylings.rb +++ b/db/migrate/20140724203302_create_stylings.rb @@ -1,4 +1,4 @@ -class CreateStylings < ActiveRecord::Migration +class CreateStylings < ActiveRecord::Migration[4.2] def change create_table :stylings do |t| t.references :stylable, polymorphic: true, null: false diff --git a/db/migrate/20140724204932_create_answers.rb b/db/migrate/20140724204932_create_answers.rb index 939174f2..d6a0ea31 100644 --- a/db/migrate/20140724204932_create_answers.rb +++ b/db/migrate/20140724204932_create_answers.rb @@ -1,4 +1,4 @@ -class CreateAnswers < ActiveRecord::Migration +class CreateAnswers < ActiveRecord::Migration[4.2] def change create_table :answers do |t| t.references :question, null: false diff --git a/db/migrate/20140724211735_create_combo_choices.rb b/db/migrate/20140724211735_create_combo_choices.rb index 0f761de1..99508bc9 100644 --- a/db/migrate/20140724211735_create_combo_choices.rb +++ b/db/migrate/20140724211735_create_combo_choices.rb @@ -1,4 +1,4 @@ -class CreateComboChoices < ActiveRecord::Migration +class CreateComboChoices < ActiveRecord::Migration[4.2] def change create_table :combo_choices do |t| t.references :stem, null: false diff --git a/db/migrate/20140724211804_create_combo_choice_answers.rb b/db/migrate/20140724211804_create_combo_choice_answers.rb index 7e534880..e08f480c 100644 --- a/db/migrate/20140724211804_create_combo_choice_answers.rb +++ b/db/migrate/20140724211804_create_combo_choice_answers.rb @@ -1,4 +1,4 @@ -class CreateComboChoiceAnswers < ActiveRecord::Migration +class CreateComboChoiceAnswers < ActiveRecord::Migration[4.2] def change create_table :combo_choice_answers do |t| t.references :combo_choice, null: false diff --git a/db/migrate/20140728144750_create_solutions.rb b/db/migrate/20140728144750_create_solutions.rb index d1f37741..316f4c18 100644 --- a/db/migrate/20140728144750_create_solutions.rb +++ b/db/migrate/20140728144750_create_solutions.rb @@ -1,4 +1,4 @@ -class CreateSolutions < ActiveRecord::Migration +class CreateSolutions < ActiveRecord::Migration[4.2] def change create_table :solutions do |t| t.references :question, null: false diff --git a/db/migrate/20140728145131_create_derivations.rb b/db/migrate/20140728145131_create_derivations.rb index aa9abd56..09a01d64 100644 --- a/db/migrate/20140728145131_create_derivations.rb +++ b/db/migrate/20140728145131_create_derivations.rb @@ -1,4 +1,4 @@ -class CreateDerivations < ActiveRecord::Migration +class CreateDerivations < ActiveRecord::Migration[4.2] def change create_table :derivations do |t| t.sortable diff --git a/db/migrate/20140728145209_create_licenses.rb b/db/migrate/20140728145209_create_licenses.rb index 95c75ab4..a06efbd7 100644 --- a/db/migrate/20140728145209_create_licenses.rb +++ b/db/migrate/20140728145209_create_licenses.rb @@ -1,4 +1,4 @@ -class CreateLicenses < ActiveRecord::Migration +class CreateLicenses < ActiveRecord::Migration[4.2] def change create_table :licenses do |t| t.string :name, null: false diff --git a/db/migrate/20140728145518_create_question_dependencies.rb b/db/migrate/20140728145518_create_question_dependencies.rb index 04e35fb9..70aa2329 100644 --- a/db/migrate/20140728145518_create_question_dependencies.rb +++ b/db/migrate/20140728145518_create_question_dependencies.rb @@ -1,4 +1,4 @@ -class CreateQuestionDependencies < ActiveRecord::Migration +class CreateQuestionDependencies < ActiveRecord::Migration[4.2] def change create_table :question_dependencies do |t| t.references :parent_question, null: false diff --git a/db/migrate/20140728180028_create_lists.rb b/db/migrate/20140728180028_create_lists.rb index b88fed20..5ccdb62e 100644 --- a/db/migrate/20140728180028_create_lists.rb +++ b/db/migrate/20140728180028_create_lists.rb @@ -1,4 +1,4 @@ -class CreateLists < ActiveRecord::Migration +class CreateLists < ActiveRecord::Migration[4.2] def change create_table :lists do |t| t.string :name, null: false diff --git a/db/migrate/20140728191217_create_list_exercises.rb b/db/migrate/20140728191217_create_list_exercises.rb index 9451d1d4..58e82f5c 100644 --- a/db/migrate/20140728191217_create_list_exercises.rb +++ b/db/migrate/20140728191217_create_list_exercises.rb @@ -1,4 +1,4 @@ -class CreateListExercises < ActiveRecord::Migration +class CreateListExercises < ActiveRecord::Migration[4.2] def change create_table :list_exercises do |t| t.sortable diff --git a/db/migrate/20140728193853_create_attachments.rb b/db/migrate/20140728193853_create_attachments.rb index b0962d92..18d80ada 100644 --- a/db/migrate/20140728193853_create_attachments.rb +++ b/db/migrate/20140728193853_create_attachments.rb @@ -1,4 +1,4 @@ -class CreateAttachments < ActiveRecord::Migration +class CreateAttachments < ActiveRecord::Migration[4.2] def change create_table :attachments do |t| t.references :parent, polymorphic: true, null: false diff --git a/db/migrate/20140728222603_create_logics.rb b/db/migrate/20140728222603_create_logics.rb index 5a20010f..eea4613e 100644 --- a/db/migrate/20140728222603_create_logics.rb +++ b/db/migrate/20140728222603_create_logics.rb @@ -1,4 +1,4 @@ -class CreateLogics < ActiveRecord::Migration +class CreateLogics < ActiveRecord::Migration[4.2] def change create_table :logics do |t| t.references :parent, polymorphic: true, null: false diff --git a/db/migrate/20140728223106_create_logic_variables.rb b/db/migrate/20140728223106_create_logic_variables.rb index c9c04f41..28471eda 100644 --- a/db/migrate/20140728223106_create_logic_variables.rb +++ b/db/migrate/20140728223106_create_logic_variables.rb @@ -1,4 +1,4 @@ -class CreateLogicVariables < ActiveRecord::Migration +class CreateLogicVariables < ActiveRecord::Migration[4.2] def change create_table :logic_variables do |t| t.references :logic, null: false diff --git a/db/migrate/20140728223606_create_logic_variable_values.rb b/db/migrate/20140728223606_create_logic_variable_values.rb index 25626db6..cd1d78db 100644 --- a/db/migrate/20140728223606_create_logic_variable_values.rb +++ b/db/migrate/20140728223606_create_logic_variable_values.rb @@ -1,4 +1,4 @@ -class CreateLogicVariableValues < ActiveRecord::Migration +class CreateLogicVariableValues < ActiveRecord::Migration[4.2] def change create_table :logic_variable_values do |t| t.references :logic_variable, null: false diff --git a/db/migrate/20140819211115_create_deputizations.rb b/db/migrate/20140819211115_create_deputizations.rb index 261cb0cd..88e92e6d 100644 --- a/db/migrate/20140819211115_create_deputizations.rb +++ b/db/migrate/20140819211115_create_deputizations.rb @@ -1,4 +1,4 @@ -class CreateDeputizations < ActiveRecord::Migration +class CreateDeputizations < ActiveRecord::Migration[4.2] def change create_table :deputizations do |t| t.references :deputizer, null: false diff --git a/db/migrate/20140821185536_create_list_owners.rb b/db/migrate/20140821185536_create_list_owners.rb index f5d34a3c..b15da193 100644 --- a/db/migrate/20140821185536_create_list_owners.rb +++ b/db/migrate/20140821185536_create_list_owners.rb @@ -1,4 +1,4 @@ -class CreateListOwners < ActiveRecord::Migration +class CreateListOwners < ActiveRecord::Migration[4.2] def change create_table :list_owners do |t| t.references :owner, polymorphic: true, null: false diff --git a/db/migrate/20140821185603_create_list_editors.rb b/db/migrate/20140821185603_create_list_editors.rb index 541cf47b..4ddad004 100644 --- a/db/migrate/20140821185603_create_list_editors.rb +++ b/db/migrate/20140821185603_create_list_editors.rb @@ -1,4 +1,4 @@ -class CreateListEditors < ActiveRecord::Migration +class CreateListEditors < ActiveRecord::Migration[4.2] def change create_table :list_editors do |t| t.references :editor, polymorphic: true, null: false diff --git a/db/migrate/20140821185624_create_list_readers.rb b/db/migrate/20140821185624_create_list_readers.rb index a486348d..75c5d458 100644 --- a/db/migrate/20140821185624_create_list_readers.rb +++ b/db/migrate/20140821185624_create_list_readers.rb @@ -1,4 +1,4 @@ -class CreateListReaders < ActiveRecord::Migration +class CreateListReaders < ActiveRecord::Migration[4.2] def change create_table :list_readers do |t| t.references :reader, polymorphic: true, null: false diff --git a/db/migrate/20140822204013_create_publications.rb b/db/migrate/20140822204013_create_publications.rb index bd7792c2..942e0957 100644 --- a/db/migrate/20140822204013_create_publications.rb +++ b/db/migrate/20140822204013_create_publications.rb @@ -1,4 +1,4 @@ -class CreatePublications < ActiveRecord::Migration +class CreatePublications < ActiveRecord::Migration[4.2] def change create_table :publications do |t| t.references :publishable, polymorphic: true, null: false diff --git a/db/migrate/20140827193017_create_license_compatibilities.rb b/db/migrate/20140827193017_create_license_compatibilities.rb index 5ea26ca5..2204c624 100644 --- a/db/migrate/20140827193017_create_license_compatibilities.rb +++ b/db/migrate/20140827193017_create_license_compatibilities.rb @@ -1,4 +1,4 @@ -class CreateLicenseCompatibilities < ActiveRecord::Migration +class CreateLicenseCompatibilities < ActiveRecord::Migration[4.2] def change create_table :license_compatibilities do |t| t.references :original_license, null: false diff --git a/db/migrate/20140827221742_create_list_nestings.rb b/db/migrate/20140827221742_create_list_nestings.rb index 7e123491..dcce34a2 100644 --- a/db/migrate/20140827221742_create_list_nestings.rb +++ b/db/migrate/20140827221742_create_list_nestings.rb @@ -1,4 +1,4 @@ -class CreateListNestings < ActiveRecord::Migration +class CreateListNestings < ActiveRecord::Migration[4.2] def change create_table :list_nestings do |t| t.references :parent_list, null: false diff --git a/db/migrate/20140828151517_create_class_licenses.rb b/db/migrate/20140828151517_create_class_licenses.rb index 9d2792a4..84d5f6d1 100644 --- a/db/migrate/20140828151517_create_class_licenses.rb +++ b/db/migrate/20140828151517_create_class_licenses.rb @@ -1,4 +1,4 @@ -class CreateClassLicenses < ActiveRecord::Migration +class CreateClassLicenses < ActiveRecord::Migration[4.2] def change create_table :class_licenses do |t| t.sortable diff --git a/db/migrate/20140904205107_create_trusted_applications.rb b/db/migrate/20140904205107_create_trusted_applications.rb index 7db3f147..5ce3607f 100644 --- a/db/migrate/20140904205107_create_trusted_applications.rb +++ b/db/migrate/20140904205107_create_trusted_applications.rb @@ -1,4 +1,4 @@ -class CreateTrustedApplications < ActiveRecord::Migration +class CreateTrustedApplications < ActiveRecord::Migration[4.2] def change create_table :trusted_applications do |t| t.references :application, null: false diff --git a/db/migrate/20140916214330_create_editors.rb b/db/migrate/20140916214330_create_editors.rb index 594d2e9c..1ada023b 100644 --- a/db/migrate/20140916214330_create_editors.rb +++ b/db/migrate/20140916214330_create_editors.rb @@ -1,4 +1,4 @@ -class CreateEditors < ActiveRecord::Migration +class CreateEditors < ActiveRecord::Migration[4.2] def change create_table :editors do |t| t.sortable diff --git a/db/migrate/20140916214350_create_authors.rb b/db/migrate/20140916214350_create_authors.rb index 90d6d903..ef89cd01 100644 --- a/db/migrate/20140916214350_create_authors.rb +++ b/db/migrate/20140916214350_create_authors.rb @@ -1,4 +1,4 @@ -class CreateAuthors < ActiveRecord::Migration +class CreateAuthors < ActiveRecord::Migration[4.2] def change create_table :authors do |t| t.sortable diff --git a/db/migrate/20140916214406_create_copyright_holders.rb b/db/migrate/20140916214406_create_copyright_holders.rb index db9b0a02..cce05df1 100644 --- a/db/migrate/20140916214406_create_copyright_holders.rb +++ b/db/migrate/20140916214406_create_copyright_holders.rb @@ -1,4 +1,4 @@ -class CreateCopyrightHolders < ActiveRecord::Migration +class CreateCopyrightHolders < ActiveRecord::Migration[4.2] def change create_table :copyright_holders do |t| t.sortable diff --git a/db/migrate/20141107194147_create_stem_answers.rb b/db/migrate/20141107194147_create_stem_answers.rb index b645db07..05cd9564 100644 --- a/db/migrate/20141107194147_create_stem_answers.rb +++ b/db/migrate/20141107194147_create_stem_answers.rb @@ -1,4 +1,4 @@ -class CreateStemAnswers < ActiveRecord::Migration +class CreateStemAnswers < ActiveRecord::Migration[4.2] def change create_table :stem_answers do |t| t.references :stem, null: false diff --git a/db/migrate/20141118174146_create_hints.rb b/db/migrate/20141118174146_create_hints.rb index d62368ab..a1f81acb 100644 --- a/db/migrate/20141118174146_create_hints.rb +++ b/db/migrate/20141118174146_create_hints.rb @@ -1,4 +1,4 @@ -class CreateHints < ActiveRecord::Migration +class CreateHints < ActiveRecord::Migration[4.2] def change create_table :hints do |t| t.sortable diff --git a/db/migrate/20150225002223_create_tags.rb b/db/migrate/20150225002223_create_tags.rb index 336d30a4..ceab1921 100644 --- a/db/migrate/20150225002223_create_tags.rb +++ b/db/migrate/20150225002223_create_tags.rb @@ -1,4 +1,4 @@ -class CreateTags < ActiveRecord::Migration +class CreateTags < ActiveRecord::Migration[4.2] def change create_table :tags do |t| t.string :name, null: false diff --git a/db/migrate/20150225002247_create_exercise_tags.rb b/db/migrate/20150225002247_create_exercise_tags.rb index e854e9a8..470eaf63 100644 --- a/db/migrate/20150225002247_create_exercise_tags.rb +++ b/db/migrate/20150225002247_create_exercise_tags.rb @@ -1,4 +1,4 @@ -class CreateExerciseTags < ActiveRecord::Migration +class CreateExerciseTags < ActiveRecord::Migration[4.2] def change create_table :exercise_tags do |t| t.references :exercise, null: false diff --git a/db/migrate/20160212204251_add_sort_position_to_answers.rb b/db/migrate/20160212204251_add_sort_position_to_answers.rb index 1cc22140..e7998b8a 100644 --- a/db/migrate/20160212204251_add_sort_position_to_answers.rb +++ b/db/migrate/20160212204251_add_sort_position_to_answers.rb @@ -1,4 +1,4 @@ -class AddSortPositionToAnswers < ActiveRecord::Migration +class AddSortPositionToAnswers < ActiveRecord::Migration[4.2] def change add_sortable_column :answers, null: false add_sortable_index :answers, scope: :question_id diff --git a/db/migrate/20160212211016_add_answer_order_matters_to_questions.rb b/db/migrate/20160212211016_add_answer_order_matters_to_questions.rb index ee2a30f2..634cceda 100644 --- a/db/migrate/20160212211016_add_answer_order_matters_to_questions.rb +++ b/db/migrate/20160212211016_add_answer_order_matters_to_questions.rb @@ -1,4 +1,4 @@ -class AddAnswerOrderMattersToQuestions < ActiveRecord::Migration +class AddAnswerOrderMattersToQuestions < ActiveRecord::Migration[4.2] def change add_column :questions, :answer_order_matters, :boolean, null: false, default: true end diff --git a/db/migrate/20160226221827_rename_solutions_to_collaborator_solutions.rb b/db/migrate/20160226221827_rename_solutions_to_collaborator_solutions.rb index 88e0bea7..0a4d7583 100644 --- a/db/migrate/20160226221827_rename_solutions_to_collaborator_solutions.rb +++ b/db/migrate/20160226221827_rename_solutions_to_collaborator_solutions.rb @@ -1,4 +1,4 @@ -class RenameSolutionsToCollaboratorSolutions < ActiveRecord::Migration +class RenameSolutionsToCollaboratorSolutions < ActiveRecord::Migration[4.2] def change rename_table :solutions, :collaborator_solutions end diff --git a/db/migrate/20160226222403_create_community_solutions.rb b/db/migrate/20160226222403_create_community_solutions.rb index b39ed2ba..971acbc9 100644 --- a/db/migrate/20160226222403_create_community_solutions.rb +++ b/db/migrate/20160226222403_create_community_solutions.rb @@ -1,4 +1,4 @@ -class CreateCommunitySolutions < ActiveRecord::Migration +class CreateCommunitySolutions < ActiveRecord::Migration[4.2] def change create_table :community_solutions do |t| t.references :question, null: false diff --git a/db/migrate/20160406202802_add_sort_position_to_questions.rb b/db/migrate/20160406202802_add_sort_position_to_questions.rb index f4bac700..39b5d350 100644 --- a/db/migrate/20160406202802_add_sort_position_to_questions.rb +++ b/db/migrate/20160406202802_add_sort_position_to_questions.rb @@ -1,4 +1,4 @@ -class AddSortPositionToQuestions < ActiveRecord::Migration +class AddSortPositionToQuestions < ActiveRecord::Migration[4.2] def change add_sortable_column :questions, null: false add_sortable_index :questions, scope: :exercise_id diff --git a/db/migrate/20160413220455_create_vocab_terms.rb b/db/migrate/20160413220455_create_vocab_terms.rb index 56eadbdf..97bf32fe 100644 --- a/db/migrate/20160413220455_create_vocab_terms.rb +++ b/db/migrate/20160413220455_create_vocab_terms.rb @@ -1,4 +1,4 @@ -class CreateVocabTerms < ActiveRecord::Migration +class CreateVocabTerms < ActiveRecord::Migration[4.2] def change create_table :vocab_terms do |t| t.string :name, null: false diff --git a/db/migrate/20160413220518_create_vocab_distractors.rb b/db/migrate/20160413220518_create_vocab_distractors.rb index 572816da..d600d0f5 100644 --- a/db/migrate/20160413220518_create_vocab_distractors.rb +++ b/db/migrate/20160413220518_create_vocab_distractors.rb @@ -1,4 +1,4 @@ -class CreateVocabDistractors < ActiveRecord::Migration +class CreateVocabDistractors < ActiveRecord::Migration[4.2] def change create_table :vocab_distractors do |t| t.references :vocab_term, null: false diff --git a/db/migrate/20160413222116_remove_duplicate_indices.rb b/db/migrate/20160413222116_remove_duplicate_indices.rb index e01bc495..4cb37946 100644 --- a/db/migrate/20160413222116_remove_duplicate_indices.rb +++ b/db/migrate/20160413222116_remove_duplicate_indices.rb @@ -1,4 +1,4 @@ -class RemoveDuplicateIndices < ActiveRecord::Migration +class RemoveDuplicateIndices < ActiveRecord::Migration[4.2] def change remove_index :questions, :exercise_id remove_index :answers, :question_id diff --git a/db/migrate/20160413223442_add_vocab_term_id_to_exercises.rb b/db/migrate/20160413223442_add_vocab_term_id_to_exercises.rb index 2e06ecaf..95a935e4 100644 --- a/db/migrate/20160413223442_add_vocab_term_id_to_exercises.rb +++ b/db/migrate/20160413223442_add_vocab_term_id_to_exercises.rb @@ -1,4 +1,4 @@ -class AddVocabTermIdToExercises < ActiveRecord::Migration +class AddVocabTermIdToExercises < ActiveRecord::Migration[4.2] def change add_column :exercises, :vocab_term_id, :integer diff --git a/db/migrate/20160420172854_create_vocab_term_tags.rb b/db/migrate/20160420172854_create_vocab_term_tags.rb index 81c19d1e..840a5017 100644 --- a/db/migrate/20160420172854_create_vocab_term_tags.rb +++ b/db/migrate/20160420172854_create_vocab_term_tags.rb @@ -1,4 +1,4 @@ -class CreateVocabTermTags < ActiveRecord::Migration +class CreateVocabTermTags < ActiveRecord::Migration[4.2] def change create_table :vocab_term_tags do |t| t.references :vocab_term, foreign_key: { on_update: :cascade, on_delete: :cascade } diff --git a/db/migrate/20160423000618_change_questions_answer_order_matters_default_to_false.rb b/db/migrate/20160423000618_change_questions_answer_order_matters_default_to_false.rb index f5dc4e2d..3a79e0ea 100644 --- a/db/migrate/20160423000618_change_questions_answer_order_matters_default_to_false.rb +++ b/db/migrate/20160423000618_change_questions_answer_order_matters_default_to_false.rb @@ -1,4 +1,4 @@ -class ChangeQuestionsAnswerOrderMattersDefaultToFalse < ActiveRecord::Migration +class ChangeQuestionsAnswerOrderMattersDefaultToFalse < ActiveRecord::Migration[4.2] def change change_column_default :questions, :answer_order_matters, false end diff --git a/db/migrate/20160425191417_create_list_vocab_terms.rb b/db/migrate/20160425191417_create_list_vocab_terms.rb index bb5a2d6f..5f700af4 100644 --- a/db/migrate/20160425191417_create_list_vocab_terms.rb +++ b/db/migrate/20160425191417_create_list_vocab_terms.rb @@ -1,4 +1,4 @@ -class CreateListVocabTerms < ActiveRecord::Migration +class CreateListVocabTerms < ActiveRecord::Migration[4.2] def change create_table :list_vocab_terms do |t| t.sortable diff --git a/db/migrate/20160606214816_add_default_to_vocab_terms_definition.rb b/db/migrate/20160606214816_add_default_to_vocab_terms_definition.rb index b3c5078f..e4ad35c9 100644 --- a/db/migrate/20160606214816_add_default_to_vocab_terms_definition.rb +++ b/db/migrate/20160606214816_add_default_to_vocab_terms_definition.rb @@ -1,4 +1,4 @@ -class AddDefaultToVocabTermsDefinition < ActiveRecord::Migration +class AddDefaultToVocabTermsDefinition < ActiveRecord::Migration[4.2] def change change_column_default :vocab_terms, :definition, '' end diff --git a/db/migrate/20160610191504_remove_uuid_from_cnxfeature_tags.rb b/db/migrate/20160610191504_remove_uuid_from_cnxfeature_tags.rb index ecc2d5cc..fd87673a 100644 --- a/db/migrate/20160610191504_remove_uuid_from_cnxfeature_tags.rb +++ b/db/migrate/20160610191504_remove_uuid_from_cnxfeature_tags.rb @@ -1,6 +1,6 @@ -class RemoveUuidFromCnxfeatureTags < ActiveRecord::Migration +class RemoveUuidFromCnxfeatureTags < ActiveRecord::Migration[4.2] def up - Tag.where {name.like 'context-cnxfeature:%#%'}.update_all("name = regexp_replace(name, '^context-cnxfeature:[\\w-]+#([\\w-]+)$', 'context-cnxfeature:\\1')") + Tag.where(Tag.arel_table[:name].matches('context-cnxfeature:%#%')).update_all("name = regexp_replace(name, '^context-cnxfeature:[\\w-]+#([\\w-]+)$', 'context-cnxfeature:\\1')") end def down diff --git a/db/migrate/20160922220434_create_publication_groups.rb b/db/migrate/20160922220434_create_publication_groups.rb index 6bc2cfa3..8f38063b 100644 --- a/db/migrate/20160922220434_create_publication_groups.rb +++ b/db/migrate/20160922220434_create_publication_groups.rb @@ -1,4 +1,4 @@ -class CreatePublicationGroups < ActiveRecord::Migration +class CreatePublicationGroups < ActiveRecord::Migration[4.2] def change create_table :publication_groups do |t| t.string :publishable_type, null: false, index: true diff --git a/db/migrate/20160922231345_change_publications_number_to_publication_group_id.rb b/db/migrate/20160922231345_change_publications_number_to_publication_group_id.rb index 00340082..c414ac20 100644 --- a/db/migrate/20160922231345_change_publications_number_to_publication_group_id.rb +++ b/db/migrate/20160922231345_change_publications_number_to_publication_group_id.rb @@ -1,4 +1,4 @@ -class ChangePublicationsNumberToPublicationGroupId < ActiveRecord::Migration +class ChangePublicationsNumberToPublicationGroupId < ActiveRecord::Migration[4.2] def up add_column :publications, :publication_group_id, :integer diff --git a/db/migrate/20161006223624_add_uuid_to_publications.rb b/db/migrate/20161006223624_add_uuid_to_publications.rb index 299d514d..f631156e 100644 --- a/db/migrate/20161006223624_add_uuid_to_publications.rb +++ b/db/migrate/20161006223624_add_uuid_to_publications.rb @@ -1,4 +1,4 @@ -class AddUuidToPublications < ActiveRecord::Migration +class AddUuidToPublications < ActiveRecord::Migration[4.2] def change ActiveRecord::Base.connection.execute 'CREATE EXTENSION IF NOT EXISTS "pgcrypto";' diff --git a/db/migrate/20161019223527_create_list_publication_groups.rb b/db/migrate/20161019223527_create_list_publication_groups.rb index 147cf2f7..7784937d 100644 --- a/db/migrate/20161019223527_create_list_publication_groups.rb +++ b/db/migrate/20161019223527_create_list_publication_groups.rb @@ -1,4 +1,4 @@ -class CreateListPublicationGroups < ActiveRecord::Migration +class CreateListPublicationGroups < ActiveRecord::Migration[4.2] def change create_table :list_publication_groups do |t| t.sortable diff --git a/db/migrate/20161020001239_move_list_exercises_and_list_vocab_terms_to_list_publication_groups.rb b/db/migrate/20161020001239_move_list_exercises_and_list_vocab_terms_to_list_publication_groups.rb index 9364812f..b671b858 100644 --- a/db/migrate/20161020001239_move_list_exercises_and_list_vocab_terms_to_list_publication_groups.rb +++ b/db/migrate/20161020001239_move_list_exercises_and_list_vocab_terms_to_list_publication_groups.rb @@ -1,4 +1,4 @@ -class MoveListExercisesAndListVocabTermsToListPublicationGroups < ActiveRecord::Migration +class MoveListExercisesAndListVocabTermsToListPublicationGroups < ActiveRecord::Migration[4.2] def up exercise_id_list_id_pairs = \ ActiveRecord::Base.connection.execute('SELECT list_id, exercise_id FROM list_exercises;') diff --git a/db/migrate/20161020175420_rename_distractor_term_number_to_distractor_publication_group_id.rb b/db/migrate/20161020175420_rename_distractor_term_number_to_distractor_publication_group_id.rb index de1c0ad2..bfaea894 100644 --- a/db/migrate/20161020175420_rename_distractor_term_number_to_distractor_publication_group_id.rb +++ b/db/migrate/20161020175420_rename_distractor_term_number_to_distractor_publication_group_id.rb @@ -1,4 +1,4 @@ -class RenameDistractorTermNumberToDistractorPublicationGroupId < ActiveRecord::Migration +class RenameDistractorTermNumberToDistractorPublicationGroupId < ActiveRecord::Migration[4.2] def up add_column :vocab_distractors, :distractor_publication_group_id, :integer diff --git a/db/migrate/20161020212457_drop_editors.rb b/db/migrate/20161020212457_drop_editors.rb index e2666197..61feaae3 100644 --- a/db/migrate/20161020212457_drop_editors.rb +++ b/db/migrate/20161020212457_drop_editors.rb @@ -1,4 +1,4 @@ -class DropEditors < ActiveRecord::Migration +class DropEditors < ActiveRecord::Migration[4.2] def change drop_table :editors end diff --git a/db/migrate/20161024224932_add_faculty_status_to_accounts_accounts.openstax_accounts.rb b/db/migrate/20161024224932_add_faculty_status_to_accounts_accounts.openstax_accounts.rb index 69f5218f..1b8fe542 100644 --- a/db/migrate/20161024224932_add_faculty_status_to_accounts_accounts.openstax_accounts.rb +++ b/db/migrate/20161024224932_add_faculty_status_to_accounts_accounts.openstax_accounts.rb @@ -1,5 +1,5 @@ # This migration comes from openstax_accounts (originally 5) -class AddFacultyStatusToAccountsAccounts < ActiveRecord::Migration +class AddFacultyStatusToAccountsAccounts < ActiveRecord::Migration[4.2] def change add_column :openstax_accounts_accounts, :faculty_status, :integer, default: 0, null: false add_index :openstax_accounts_accounts, :faculty_status diff --git a/db/migrate/20161024224933_add_salesforce_contact_id_to_accounts_accounts.openstax_accounts.rb b/db/migrate/20161024224933_add_salesforce_contact_id_to_accounts_accounts.openstax_accounts.rb index ab66706d..9e9625fd 100644 --- a/db/migrate/20161024224933_add_salesforce_contact_id_to_accounts_accounts.openstax_accounts.rb +++ b/db/migrate/20161024224933_add_salesforce_contact_id_to_accounts_accounts.openstax_accounts.rb @@ -1,5 +1,5 @@ # This migration comes from openstax_accounts (originally 6) -class AddSalesforceContactIdToAccountsAccounts < ActiveRecord::Migration +class AddSalesforceContactIdToAccountsAccounts < ActiveRecord::Migration[4.2] def change add_column :openstax_accounts_accounts, :salesforce_contact_id, :string add_index :openstax_accounts_accounts, :salesforce_contact_id diff --git a/db/migrate/20171109183131_change_accounts_openstax_uid_to_be_nullable.openstax_accounts.rb b/db/migrate/20171109183131_change_accounts_openstax_uid_to_be_nullable.openstax_accounts.rb index 4b270888..94d9fb48 100644 --- a/db/migrate/20171109183131_change_accounts_openstax_uid_to_be_nullable.openstax_accounts.rb +++ b/db/migrate/20171109183131_change_accounts_openstax_uid_to_be_nullable.openstax_accounts.rb @@ -1,5 +1,5 @@ # This migration comes from openstax_accounts (originally 7) -class ChangeAccountsOpenStaxUidToBeNullable < ActiveRecord::Migration +class ChangeAccountsOpenStaxUidToBeNullable < ActiveRecord::Migration[4.2] def change change_column_null :openstax_accounts_accounts, :openstax_uid, true end diff --git a/db/migrate/20171109183132_change_accounts_username_to_be_nullable.openstax_accounts.rb b/db/migrate/20171109183132_change_accounts_username_to_be_nullable.openstax_accounts.rb index d85536cc..7ad48130 100644 --- a/db/migrate/20171109183132_change_accounts_username_to_be_nullable.openstax_accounts.rb +++ b/db/migrate/20171109183132_change_accounts_username_to_be_nullable.openstax_accounts.rb @@ -1,5 +1,5 @@ # This migration comes from openstax_accounts (originally 8) -class ChangeAccountsUsernameToBeNullable < ActiveRecord::Migration +class ChangeAccountsUsernameToBeNullable < ActiveRecord::Migration[4.2] def change change_column_null :openstax_accounts_accounts, :username, true end diff --git a/db/migrate/20171109183133_add_uuid_and_role_to_accounts_accounts.openstax_accounts.rb b/db/migrate/20171109183133_add_uuid_and_role_to_accounts_accounts.openstax_accounts.rb index 54da92f2..82d3c694 100644 --- a/db/migrate/20171109183133_add_uuid_and_role_to_accounts_accounts.openstax_accounts.rb +++ b/db/migrate/20171109183133_add_uuid_and_role_to_accounts_accounts.openstax_accounts.rb @@ -1,5 +1,5 @@ # This migration comes from openstax_accounts (originally 9) -class AddUuidAndRoleToAccountsAccounts < ActiveRecord::Migration +class AddUuidAndRoleToAccountsAccounts < ActiveRecord::Migration[4.2] def change add_column :openstax_accounts_accounts, :uuid, :string add_index :openstax_accounts_accounts, :uuid, unique: true diff --git a/db/migrate/20171109210559_assign_missing_uuids_for_local_accounts.openstax_accounts.rb b/db/migrate/20171109210559_assign_missing_uuids_for_local_accounts.openstax_accounts.rb index 6a65f8c0..07878852 100644 --- a/db/migrate/20171109210559_assign_missing_uuids_for_local_accounts.openstax_accounts.rb +++ b/db/migrate/20171109210559_assign_missing_uuids_for_local_accounts.openstax_accounts.rb @@ -1,5 +1,5 @@ # This migration comes from openstax_accounts (originally 10) -class AssignMissingUuidsForLocalAccounts < ActiveRecord::Migration +class AssignMissingUuidsForLocalAccounts < ActiveRecord::Migration[4.2] def change enable_extension 'pgcrypto' diff --git a/db/migrate/20171219215854_add_previous_refresh_token_to_access_tokens.rb b/db/migrate/20171219215854_add_previous_refresh_token_to_access_tokens.rb index e3f07e35..263e3ff3 100644 --- a/db/migrate/20171219215854_add_previous_refresh_token_to_access_tokens.rb +++ b/db/migrate/20171219215854_add_previous_refresh_token_to_access_tokens.rb @@ -1,4 +1,4 @@ -class AddPreviousRefreshTokenToAccessTokens < ActiveRecord::Migration +class AddPreviousRefreshTokenToAccessTokens < ActiveRecord::Migration[4.2] def change add_column( :oauth_access_tokens, diff --git a/db/migrate/20171220232359_add_support_identifier_to_accounts_accounts.openstax_accounts.rb b/db/migrate/20171220232359_add_support_identifier_to_accounts_accounts.openstax_accounts.rb index fec75d43..ada20ba0 100644 --- a/db/migrate/20171220232359_add_support_identifier_to_accounts_accounts.openstax_accounts.rb +++ b/db/migrate/20171220232359_add_support_identifier_to_accounts_accounts.openstax_accounts.rb @@ -1,5 +1,5 @@ # This migration comes from openstax_accounts (originally 11) -class AddSupportIdentifierToAccountsAccounts < ActiveRecord::Migration +class AddSupportIdentifierToAccountsAccounts < ActiveRecord::Migration[4.2] def change enable_extension :citext diff --git a/db/migrate/20171222002015_add_is_test_to_accounts_accounts.openstax_accounts.rb b/db/migrate/20171222002015_add_is_test_to_accounts_accounts.openstax_accounts.rb index 4d4b3b73..e592ca13 100644 --- a/db/migrate/20171222002015_add_is_test_to_accounts_accounts.openstax_accounts.rb +++ b/db/migrate/20171222002015_add_is_test_to_accounts_accounts.openstax_accounts.rb @@ -1,5 +1,5 @@ # This migration comes from openstax_accounts (originally 12) -class AddIsTestToAccountsAccounts < ActiveRecord::Migration +class AddIsTestToAccountsAccounts < ActiveRecord::Migration[4.2] def change add_column :openstax_accounts_accounts, :is_test, :boolean end diff --git a/db/migrate/20180131161122_improve_publication_publication_group_index.rb b/db/migrate/20180131161122_improve_publication_publication_group_index.rb index 916328d6..2b332d19 100644 --- a/db/migrate/20180131161122_improve_publication_publication_group_index.rb +++ b/db/migrate/20180131161122_improve_publication_publication_group_index.rb @@ -1,4 +1,4 @@ -class ImprovePublicationPublicationGroupIndex < ActiveRecord::Migration +class ImprovePublicationPublicationGroupIndex < ActiveRecord::Migration[4.2] def change remove_index :publications, :publication_group_id diff --git a/db/migrate/20180131161240_add_latest_published_version_to_publication_groups.rb b/db/migrate/20180131161240_add_latest_published_version_to_publication_groups.rb index 3496cfb9..f1575ba0 100644 --- a/db/migrate/20180131161240_add_latest_published_version_to_publication_groups.rb +++ b/db/migrate/20180131161240_add_latest_published_version_to_publication_groups.rb @@ -1,4 +1,4 @@ -class AddLatestPublishedVersionToPublicationGroups < ActiveRecord::Migration +class AddLatestPublishedVersionToPublicationGroups < ActiveRecord::Migration[4.2] def change add_column :publication_groups, :latest_version, :integer add_column :publication_groups, :latest_published_version, :integer diff --git a/db/migrate/20180220213530_add_nickname_to_publication_group.rb b/db/migrate/20180220213530_add_nickname_to_publication_group.rb index aa477e6b..c151cbb2 100644 --- a/db/migrate/20180220213530_add_nickname_to_publication_group.rb +++ b/db/migrate/20180220213530_add_nickname_to_publication_group.rb @@ -1,4 +1,4 @@ -class AddNicknameToPublicationGroup < ActiveRecord::Migration +class AddNicknameToPublicationGroup < ActiveRecord::Migration[4.2] def change add_column :publication_groups, :nickname, :string add_index :publication_groups, :nickname, unique: true diff --git a/db/migrate/20180829201038_add_a15k_fields.rb b/db/migrate/20180829201038_add_a15k_fields.rb index 489ee122..1dff759c 100644 --- a/db/migrate/20180829201038_add_a15k_fields.rb +++ b/db/migrate/20180829201038_add_a15k_fields.rb @@ -1,4 +1,4 @@ -class AddA15kFields < ActiveRecord::Migration +class AddA15kFields < ActiveRecord::Migration[4.2] def change add_column :exercises, :a15k_identifier, :string, index: true add_column :exercises, :a15k_version, :integer diff --git a/db/migrate/20180927223921_add_confidential_to_applications.rb b/db/migrate/20180927223921_add_confidential_to_applications.rb index 5e01a963..06d66fd6 100644 --- a/db/migrate/20180927223921_add_confidential_to_applications.rb +++ b/db/migrate/20180927223921_add_confidential_to_applications.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class AddConfidentialToApplications < ActiveRecord::Migration +class AddConfidentialToApplications < ActiveRecord::Migration[4.2] def change add_column( :oauth_applications, diff --git a/db/migrate/20180927223943_add_missing_doorkeeper_foreign_keys.rb b/db/migrate/20180927223943_add_missing_doorkeeper_foreign_keys.rb index 8340ffde..f13466db 100644 --- a/db/migrate/20180927223943_add_missing_doorkeeper_foreign_keys.rb +++ b/db/migrate/20180927223943_add_missing_doorkeeper_foreign_keys.rb @@ -1,4 +1,4 @@ -class AddMissingDoorkeeperForeignKeys < ActiveRecord::Migration +class AddMissingDoorkeeperForeignKeys < ActiveRecord::Migration[4.2] def change add_foreign_key( :oauth_access_grants, diff --git a/db/migrate/20190308184133_add_implicit_signatures.fine_print.rb b/db/migrate/20190308184133_add_implicit_signatures.fine_print.rb index 0ed326fc..39d32837 100644 --- a/db/migrate/20190308184133_add_implicit_signatures.fine_print.rb +++ b/db/migrate/20190308184133_add_implicit_signatures.fine_print.rb @@ -1,5 +1,5 @@ # This migration comes from fine_print (originally 1) -class AddImplicitSignatures < ActiveRecord::Migration +class AddImplicitSignatures < ActiveRecord::Migration[4.2] def change add_column :fine_print_signatures, :is_implicit, :boolean, null: false, default: false diff --git a/db/migrate/20190517204620_add_school_type_to_accounts_accounts.openstax_accounts.rb b/db/migrate/20190517204620_add_school_type_to_accounts_accounts.openstax_accounts.rb new file mode 100644 index 00000000..1c042203 --- /dev/null +++ b/db/migrate/20190517204620_add_school_type_to_accounts_accounts.openstax_accounts.rb @@ -0,0 +1,7 @@ +# This migration comes from openstax_accounts (originally 13) +class AddSchoolTypeToAccountsAccounts < ActiveRecord::Migration[4.2] + def change + add_column :openstax_accounts_accounts, :school_type, :integer, null: false, default: 0 + add_index :openstax_accounts_accounts, :school_type + end +end diff --git a/db/schema.rb b/db/schema.rb index 0f76af02..609daf5f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1,4 +1,3 @@ -# encoding: UTF-8 # 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. @@ -11,655 +10,605 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20190308184133) do +ActiveRecord::Schema.define(version: 2019_05_17_204620) do # These are extensions that must be enabled in order to support this database - enable_extension "plpgsql" - enable_extension "pgcrypto" enable_extension "citext" + enable_extension "pgcrypto" + enable_extension "plpgsql" + enable_extension "uuid-ossp" - create_table "administrators", force: :cascade do |t| - t.integer "user_id", null: false + create_table "administrators", id: :serial, force: :cascade do |t| + t.integer "user_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.index ["user_id"], name: "index_administrators_on_user_id", unique: true end - add_index "administrators", ["user_id"], name: "index_administrators_on_user_id", unique: true, using: :btree - - create_table "answers", force: :cascade do |t| - t.integer "question_id", null: false - t.text "content", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "sort_position", null: false + create_table "answers", id: :serial, force: :cascade do |t| + t.integer "question_id", null: false + t.text "content", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "sort_position", null: false + t.index ["question_id", "sort_position"], name: "index_answers_on_question_id_and_sort_position", unique: true end - add_index "answers", ["question_id", "sort_position"], name: "index_answers_on_question_id_and_sort_position", unique: true, using: :btree - - create_table "attachments", force: :cascade do |t| - t.integer "parent_id", null: false - t.string "parent_type", null: false - t.string "asset", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "attachments", id: :serial, force: :cascade do |t| + t.integer "parent_id", null: false + t.string "parent_type", null: false + t.string "asset", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["asset"], name: "index_attachments_on_asset" + t.index ["parent_id", "parent_type", "asset"], name: "index_attachments_on_parent_id_and_parent_type_and_asset", unique: true end - add_index "attachments", ["asset"], name: "index_attachments_on_asset", using: :btree - add_index "attachments", ["parent_id", "parent_type", "asset"], name: "index_attachments_on_parent_id_and_parent_type_and_asset", unique: true, using: :btree - - create_table "authors", force: :cascade do |t| - t.integer "sort_position", null: false - t.integer "publication_id", null: false - t.integer "user_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "authors", id: :serial, force: :cascade do |t| + t.integer "sort_position", null: false + t.integer "publication_id", null: false + t.integer "user_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["publication_id", "sort_position"], name: "index_authors_on_publication_id_and_sort_position", unique: true + t.index ["user_id", "publication_id"], name: "index_authors_on_user_id_and_publication_id", unique: true end - add_index "authors", ["publication_id", "sort_position"], name: "index_authors_on_publication_id_and_sort_position", unique: true, using: :btree - add_index "authors", ["user_id", "publication_id"], name: "index_authors_on_user_id_and_publication_id", unique: true, using: :btree - - create_table "class_licenses", force: :cascade do |t| - t.integer "sort_position", null: false - t.integer "license_id", null: false - t.string "class_name", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "class_licenses", id: :serial, force: :cascade do |t| + t.integer "sort_position", null: false + t.integer "license_id", null: false + t.string "class_name", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["class_name", "sort_position"], name: "index_class_licenses_on_class_name_and_sort_position", unique: true + t.index ["license_id", "class_name"], name: "index_class_licenses_on_license_id_and_class_name", unique: true end - add_index "class_licenses", ["class_name", "sort_position"], name: "index_class_licenses_on_class_name_and_sort_position", unique: true, using: :btree - add_index "class_licenses", ["license_id", "class_name"], name: "index_class_licenses_on_license_id_and_class_name", unique: true, using: :btree - - create_table "collaborator_solutions", force: :cascade do |t| - t.integer "question_id", null: false - t.string "title" - t.text "solution_type", null: false - t.text "content", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "collaborator_solutions", id: :serial, force: :cascade do |t| + t.integer "question_id", null: false + t.string "title" + t.text "solution_type", null: false + t.text "content", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["question_id"], name: "index_collaborator_solutions_on_question_id" + t.index ["solution_type"], name: "index_collaborator_solutions_on_solution_type" + t.index ["title"], name: "index_collaborator_solutions_on_title" end - add_index "collaborator_solutions", ["question_id"], name: "index_collaborator_solutions_on_question_id", using: :btree - add_index "collaborator_solutions", ["solution_type"], name: "index_collaborator_solutions_on_solution_type", using: :btree - add_index "collaborator_solutions", ["title"], name: "index_collaborator_solutions_on_title", using: :btree - - create_table "combo_choice_answers", force: :cascade do |t| - t.integer "combo_choice_id", null: false - t.integer "answer_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "combo_choice_answers", id: :serial, force: :cascade do |t| + t.integer "combo_choice_id", null: false + t.integer "answer_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["answer_id", "combo_choice_id"], name: "index_combo_choice_answers_on_answer_id_and_combo_choice_id", unique: true + t.index ["combo_choice_id"], name: "index_combo_choice_answers_on_combo_choice_id" end - add_index "combo_choice_answers", ["answer_id", "combo_choice_id"], name: "index_combo_choice_answers_on_answer_id_and_combo_choice_id", unique: true, using: :btree - add_index "combo_choice_answers", ["combo_choice_id"], name: "index_combo_choice_answers_on_combo_choice_id", using: :btree - - create_table "combo_choices", force: :cascade do |t| - t.integer "stem_id", null: false - t.decimal "correctness", precision: 3, scale: 2, default: 0.0, null: false - t.text "feedback" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "combo_choices", id: :serial, force: :cascade do |t| + t.integer "stem_id", null: false + t.decimal "correctness", precision: 3, scale: 2, default: "0.0", null: false + t.text "feedback" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["stem_id", "correctness"], name: "index_combo_choices_on_stem_id_and_correctness" end - add_index "combo_choices", ["stem_id", "correctness"], name: "index_combo_choices_on_stem_id_and_correctness", using: :btree - - create_table "commontator_comments", force: :cascade do |t| - t.string "creator_type" - t.integer "creator_id" - t.string "editor_type" - t.integer "editor_id" - t.integer "thread_id", null: false - t.text "body", null: false + create_table "commontator_comments", id: :serial, force: :cascade do |t| + t.string "creator_type" + t.integer "creator_id" + t.string "editor_type" + t.integer "editor_id" + t.integer "thread_id", null: false + t.text "body", null: false t.datetime "deleted_at" - t.integer "cached_votes_up", default: 0 - t.integer "cached_votes_down", default: 0 - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.integer "cached_votes_up", default: 0 + t.integer "cached_votes_down", default: 0 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["cached_votes_down"], name: "index_commontator_comments_on_cached_votes_down" + t.index ["cached_votes_up"], name: "index_commontator_comments_on_cached_votes_up" + t.index ["creator_id", "creator_type", "thread_id"], name: "index_commontator_comments_on_c_id_and_c_type_and_t_id" + t.index ["thread_id", "created_at"], name: "index_commontator_comments_on_thread_id_and_created_at" end - add_index "commontator_comments", ["cached_votes_down"], name: "index_commontator_comments_on_cached_votes_down", using: :btree - add_index "commontator_comments", ["cached_votes_up"], name: "index_commontator_comments_on_cached_votes_up", using: :btree - add_index "commontator_comments", ["creator_id", "creator_type", "thread_id"], name: "index_commontator_comments_on_c_id_and_c_type_and_t_id", using: :btree - add_index "commontator_comments", ["thread_id", "created_at"], name: "index_commontator_comments_on_thread_id_and_created_at", using: :btree - - create_table "commontator_subscriptions", force: :cascade do |t| - t.string "subscriber_type", null: false - t.integer "subscriber_id", null: false - t.integer "thread_id", null: false + create_table "commontator_subscriptions", id: :serial, force: :cascade do |t| + t.string "subscriber_type", null: false + t.integer "subscriber_id", null: false + t.integer "thread_id", null: false t.datetime "created_at" t.datetime "updated_at" + t.index ["subscriber_id", "subscriber_type", "thread_id"], name: "index_commontator_subscriptions_on_s_id_and_s_type_and_t_id", unique: true + t.index ["thread_id"], name: "index_commontator_subscriptions_on_thread_id" end - add_index "commontator_subscriptions", ["subscriber_id", "subscriber_type", "thread_id"], name: "index_commontator_subscriptions_on_s_id_and_s_type_and_t_id", unique: true, using: :btree - add_index "commontator_subscriptions", ["thread_id"], name: "index_commontator_subscriptions_on_thread_id", using: :btree - - create_table "commontator_threads", force: :cascade do |t| - t.string "commontable_type" - t.integer "commontable_id" + create_table "commontator_threads", id: :serial, force: :cascade do |t| + t.string "commontable_type" + t.integer "commontable_id" t.datetime "closed_at" - t.string "closer_type" - t.integer "closer_id" + t.string "closer_type" + t.integer "closer_id" t.datetime "created_at" t.datetime "updated_at" + t.index ["commontable_id", "commontable_type"], name: "index_commontator_threads_on_c_id_and_c_type", unique: true end - add_index "commontator_threads", ["commontable_id", "commontable_type"], name: "index_commontator_threads_on_c_id_and_c_type", unique: true, using: :btree - - create_table "community_solutions", force: :cascade do |t| - t.integer "question_id", null: false - t.string "title" - t.text "solution_type", null: false - t.text "content", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "community_solutions", id: :serial, force: :cascade do |t| + t.integer "question_id", null: false + t.string "title" + t.text "solution_type", null: false + t.text "content", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["question_id"], name: "index_community_solutions_on_question_id" + t.index ["solution_type"], name: "index_community_solutions_on_solution_type" + t.index ["title"], name: "index_community_solutions_on_title" end - add_index "community_solutions", ["question_id"], name: "index_community_solutions_on_question_id", using: :btree - add_index "community_solutions", ["solution_type"], name: "index_community_solutions_on_solution_type", using: :btree - add_index "community_solutions", ["title"], name: "index_community_solutions_on_title", using: :btree - - create_table "copyright_holders", force: :cascade do |t| - t.integer "sort_position", null: false - t.integer "publication_id", null: false - t.integer "user_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "copyright_holders", id: :serial, force: :cascade do |t| + t.integer "sort_position", null: false + t.integer "publication_id", null: false + t.integer "user_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["publication_id", "sort_position"], name: "index_copyright_holders_on_publication_id_and_sort_position", unique: true + t.index ["user_id", "publication_id"], name: "index_copyright_holders_on_user_id_and_publication_id", unique: true end - add_index "copyright_holders", ["publication_id", "sort_position"], name: "index_copyright_holders_on_publication_id_and_sort_position", unique: true, using: :btree - add_index "copyright_holders", ["user_id", "publication_id"], name: "index_copyright_holders_on_user_id_and_publication_id", unique: true, using: :btree - - create_table "deputizations", force: :cascade do |t| - t.integer "deputizer_id", null: false - t.integer "deputy_id", null: false - t.string "deputy_type", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "deputizations", id: :serial, force: :cascade do |t| + t.integer "deputizer_id", null: false + t.integer "deputy_id", null: false + t.string "deputy_type", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["deputizer_id"], name: "index_deputizations_on_deputizer_id" + t.index ["deputy_id", "deputy_type", "deputizer_id"], name: "index_deputizations_on_d_id_and_d_type_and_d_id", unique: true end - add_index "deputizations", ["deputizer_id"], name: "index_deputizations_on_deputizer_id", using: :btree - add_index "deputizations", ["deputy_id", "deputy_type", "deputizer_id"], name: "index_deputizations_on_d_id_and_d_type_and_d_id", unique: true, using: :btree - - create_table "derivations", force: :cascade do |t| - t.integer "sort_position", null: false - t.integer "derived_publication_id", null: false - t.integer "source_publication_id" - t.text "custom_attribution" + create_table "derivations", id: :serial, force: :cascade do |t| + t.integer "sort_position", null: false + t.integer "derived_publication_id", null: false + t.integer "source_publication_id" + t.text "custom_attribution" t.datetime "hidden_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - end - - add_index "derivations", ["derived_publication_id", "hidden_at"], name: "index_derivations_on_derived_publication_id_and_hidden_at", using: :btree - add_index "derivations", ["derived_publication_id", "sort_position"], name: "index_derivations_on_derived_publication_id_and_sort_position", unique: true, using: :btree - add_index "derivations", ["source_publication_id", "derived_publication_id"], name: "index_derivations_on_source_p_id_and_derived_p_id", unique: true, using: :btree - - create_table "exercise_tags", force: :cascade do |t| - t.integer "exercise_id", null: false - t.integer "tag_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["derived_publication_id", "hidden_at"], name: "index_derivations_on_derived_publication_id_and_hidden_at" + t.index ["derived_publication_id", "sort_position"], name: "index_derivations_on_derived_publication_id_and_sort_position", unique: true + t.index ["source_publication_id", "derived_publication_id"], name: "index_derivations_on_source_p_id_and_derived_p_id", unique: true end - add_index "exercise_tags", ["exercise_id", "tag_id"], name: "index_exercise_tags_on_exercise_id_and_tag_id", unique: true, using: :btree - add_index "exercise_tags", ["tag_id"], name: "index_exercise_tags_on_tag_id", using: :btree - - create_table "exercises", force: :cascade do |t| - t.string "title" - t.text "stimulus" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "vocab_term_id" - t.string "a15k_identifier" - t.integer "a15k_version" - t.boolean "release_to_a15k" + create_table "exercise_tags", id: :serial, force: :cascade do |t| + t.integer "exercise_id", null: false + t.integer "tag_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["exercise_id", "tag_id"], name: "index_exercise_tags_on_exercise_id_and_tag_id", unique: true + t.index ["tag_id"], name: "index_exercise_tags_on_tag_id" end - add_index "exercises", ["title"], name: "index_exercises_on_title", using: :btree - add_index "exercises", ["vocab_term_id"], name: "index_exercises_on_vocab_term_id", using: :btree - - create_table "fine_print_contracts", force: :cascade do |t| - t.string "name", null: false - t.integer "version" - t.string "title", null: false - t.text "content", null: false + create_table "exercises", id: :serial, force: :cascade do |t| + t.string "title" + t.text "stimulus" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "vocab_term_id" + t.string "a15k_identifier" + t.integer "a15k_version" + t.boolean "release_to_a15k" + t.index ["title"], name: "index_exercises_on_title" + t.index ["vocab_term_id"], name: "index_exercises_on_vocab_term_id" + end + + create_table "fine_print_contracts", id: :serial, force: :cascade do |t| + t.string "name", null: false + t.integer "version" + t.string "title", null: false + t.text "content", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["name", "version"], name: "index_fine_print_contracts_on_name_and_version", unique: true end - add_index "fine_print_contracts", ["name", "version"], name: "index_fine_print_contracts_on_name_and_version", unique: true, using: :btree - - create_table "fine_print_signatures", force: :cascade do |t| - t.integer "contract_id", null: false - t.integer "user_id", null: false - t.string "user_type", null: false + create_table "fine_print_signatures", id: :serial, force: :cascade do |t| + t.integer "contract_id", null: false + t.integer "user_id", null: false + t.string "user_type", null: false t.datetime "created_at" t.datetime "updated_at" - t.boolean "is_implicit", default: false, null: false + t.boolean "is_implicit", default: false, null: false + t.index ["contract_id"], name: "index_fine_print_signatures_on_contract_id" + t.index ["user_id", "user_type", "contract_id"], name: "index_fine_print_signatures_on_u_id_and_u_type_and_c_id", unique: true end - add_index "fine_print_signatures", ["contract_id"], name: "index_fine_print_signatures_on_contract_id", using: :btree - add_index "fine_print_signatures", ["user_id", "user_type", "contract_id"], name: "index_fine_print_signatures_on_u_id_and_u_type_and_c_id", unique: true, using: :btree - - create_table "hints", force: :cascade do |t| - t.integer "sort_position", null: false - t.integer "question_id", null: false - t.text "content", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "hints", id: :serial, force: :cascade do |t| + t.integer "sort_position", null: false + t.integer "question_id", null: false + t.text "content", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["question_id", "sort_position"], name: "index_hints_on_question_id_and_sort_position", unique: true end - add_index "hints", ["question_id", "sort_position"], name: "index_hints_on_question_id_and_sort_position", unique: true, using: :btree - - create_table "license_compatibilities", force: :cascade do |t| - t.integer "original_license_id", null: false - t.integer "combined_license_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "license_compatibilities", id: :serial, force: :cascade do |t| + t.integer "original_license_id", null: false + t.integer "combined_license_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["combined_license_id", "original_license_id"], name: "index_license_compatibilities_on_c_l_id_and_o_l_id", unique: true + t.index ["original_license_id"], name: "index_license_compatibilities_on_original_license_id" + end + + create_table "licenses", id: :serial, force: :cascade do |t| + t.string "name", null: false + t.string "title", null: false + t.string "url", null: false + t.text "publishing_contract", null: false + t.text "copyright_notice", null: false + t.boolean "requires_attribution", default: true, null: false + t.boolean "requires_share_alike", default: false, null: false + t.boolean "allows_derivatives", default: true, null: false + t.boolean "allows_commercial_use", default: true, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["name"], name: "index_licenses_on_name", unique: true + t.index ["title"], name: "index_licenses_on_title", unique: true + t.index ["url"], name: "index_licenses_on_url", unique: true end - add_index "license_compatibilities", ["combined_license_id", "original_license_id"], name: "index_license_compatibilities_on_c_l_id_and_o_l_id", unique: true, using: :btree - add_index "license_compatibilities", ["original_license_id"], name: "index_license_compatibilities_on_original_license_id", using: :btree - - create_table "licenses", force: :cascade do |t| - t.string "name", null: false - t.string "title", null: false - t.string "url", null: false - t.text "publishing_contract", null: false - t.text "copyright_notice", null: false - t.boolean "requires_attribution", default: true, null: false - t.boolean "requires_share_alike", default: false, null: false - t.boolean "allows_derivatives", default: true, null: false - t.boolean "allows_commercial_use", default: true, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "list_editors", id: :serial, force: :cascade do |t| + t.integer "editor_id", null: false + t.string "editor_type", null: false + t.integer "list_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["editor_id", "editor_type", "list_id"], name: "index_list_editors_on_editor_id_and_editor_type_and_list_id", unique: true + t.index ["list_id"], name: "index_list_editors_on_list_id" end - add_index "licenses", ["name"], name: "index_licenses_on_name", unique: true, using: :btree - add_index "licenses", ["title"], name: "index_licenses_on_title", unique: true, using: :btree - add_index "licenses", ["url"], name: "index_licenses_on_url", unique: true, using: :btree - - create_table "list_editors", force: :cascade do |t| - t.integer "editor_id", null: false - t.string "editor_type", null: false - t.integer "list_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "list_nestings", id: :serial, force: :cascade do |t| + t.integer "parent_list_id", null: false + t.integer "child_list_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["child_list_id"], name: "index_list_nestings_on_child_list_id", unique: true + t.index ["parent_list_id"], name: "index_list_nestings_on_parent_list_id" end - add_index "list_editors", ["editor_id", "editor_type", "list_id"], name: "index_list_editors_on_editor_id_and_editor_type_and_list_id", unique: true, using: :btree - add_index "list_editors", ["list_id"], name: "index_list_editors_on_list_id", using: :btree - - create_table "list_nestings", force: :cascade do |t| - t.integer "parent_list_id", null: false - t.integer "child_list_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "list_owners", id: :serial, force: :cascade do |t| + t.integer "owner_id", null: false + t.string "owner_type", null: false + t.integer "list_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["list_id"], name: "index_list_owners_on_list_id" + t.index ["owner_id", "owner_type", "list_id"], name: "index_list_owners_on_owner_id_and_owner_type_and_list_id", unique: true end - add_index "list_nestings", ["child_list_id"], name: "index_list_nestings_on_child_list_id", unique: true, using: :btree - add_index "list_nestings", ["parent_list_id"], name: "index_list_nestings_on_parent_list_id", using: :btree - - create_table "list_owners", force: :cascade do |t| - t.integer "owner_id", null: false - t.string "owner_type", null: false - t.integer "list_id", null: false + create_table "list_publication_groups", id: :serial, force: :cascade do |t| + t.integer "sort_position", null: false + t.integer "list_id", null: false + t.integer "publication_group_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.index ["list_id", "sort_position"], name: "index_list_publication_groups_on_list_id_and_sort_position", unique: true + t.index ["publication_group_id", "list_id"], name: "index_list_publication_groups_on_p_g_id_and_l_id", unique: true end - add_index "list_owners", ["list_id"], name: "index_list_owners_on_list_id", using: :btree - add_index "list_owners", ["owner_id", "owner_type", "list_id"], name: "index_list_owners_on_owner_id_and_owner_type_and_list_id", unique: true, using: :btree - - create_table "list_publication_groups", force: :cascade do |t| - t.integer "sort_position", null: false - t.integer "list_id", null: false - t.integer "publication_group_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "list_readers", id: :serial, force: :cascade do |t| + t.integer "reader_id", null: false + t.string "reader_type", null: false + t.integer "list_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["list_id"], name: "index_list_readers_on_list_id" + t.index ["reader_id", "reader_type", "list_id"], name: "index_list_readers_on_reader_id_and_reader_type_and_list_id", unique: true end - add_index "list_publication_groups", ["list_id", "sort_position"], name: "index_list_publication_groups_on_list_id_and_sort_position", unique: true, using: :btree - add_index "list_publication_groups", ["publication_group_id", "list_id"], name: "index_list_publication_groups_on_p_g_id_and_l_id", unique: true, using: :btree - - create_table "list_readers", force: :cascade do |t| - t.integer "reader_id", null: false - t.string "reader_type", null: false - t.integer "list_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "lists", id: :serial, force: :cascade do |t| + t.string "name", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["name"], name: "index_lists_on_name" end - add_index "list_readers", ["list_id"], name: "index_list_readers_on_list_id", using: :btree - add_index "list_readers", ["reader_id", "reader_type", "list_id"], name: "index_list_readers_on_reader_id_and_reader_type_and_list_id", unique: true, using: :btree - - create_table "lists", force: :cascade do |t| - t.string "name", null: false + create_table "logic_variable_values", id: :serial, force: :cascade do |t| + t.integer "logic_variable_id", null: false + t.integer "seed", null: false + t.text "value", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.index ["logic_variable_id", "seed"], name: "index_logic_variable_values_on_logic_variable_id_and_seed", unique: true end - add_index "lists", ["name"], name: "index_lists_on_name", using: :btree - - create_table "logic_variable_values", force: :cascade do |t| - t.integer "logic_variable_id", null: false - t.integer "seed", null: false - t.text "value", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "logic_variables", id: :serial, force: :cascade do |t| + t.integer "logic_id", null: false + t.string "variable", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["logic_id", "variable"], name: "index_logic_variables_on_logic_id_and_variable", unique: true end - add_index "logic_variable_values", ["logic_variable_id", "seed"], name: "index_logic_variable_values_on_logic_variable_id_and_seed", unique: true, using: :btree - - create_table "logic_variables", force: :cascade do |t| - t.integer "logic_id", null: false - t.string "variable", null: false + create_table "logics", id: :serial, force: :cascade do |t| + t.integer "parent_id", null: false + t.string "parent_type", null: false + t.string "language", null: false + t.text "code", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.index ["parent_id", "parent_type", "language"], name: "index_logics_on_parent_id_and_parent_type_and_language", unique: true end - add_index "logic_variables", ["logic_id", "variable"], name: "index_logic_variables_on_logic_id_and_variable", unique: true, using: :btree - - create_table "logics", force: :cascade do |t| - t.integer "parent_id", null: false - t.string "parent_type", null: false - t.string "language", null: false - t.text "code", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "oauth_access_grants", id: :serial, force: :cascade do |t| + t.integer "resource_owner_id", null: false + t.integer "application_id", null: false + t.string "token", null: false + t.integer "expires_in", null: false + t.text "redirect_uri", null: false + t.datetime "created_at", null: false + t.datetime "revoked_at" + t.string "scopes" + t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true end - add_index "logics", ["parent_id", "parent_type", "language"], name: "index_logics_on_parent_id_and_parent_type_and_language", unique: true, using: :btree - - create_table "oauth_access_grants", force: :cascade do |t| - t.integer "resource_owner_id", null: false - t.integer "application_id", null: false - t.string "token", null: false - t.integer "expires_in", null: false - t.text "redirect_uri", null: false - t.datetime "created_at", null: false + create_table "oauth_access_tokens", id: :serial, force: :cascade do |t| + t.integer "resource_owner_id" + t.integer "application_id" + t.string "token", null: false + t.string "refresh_token" + t.integer "expires_in" t.datetime "revoked_at" - t.string "scopes" + t.datetime "created_at", null: false + t.string "scopes" + t.string "previous_refresh_token", default: "", null: false + t.index ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true + t.index ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id" + t.index ["token"], name: "index_oauth_access_tokens_on_token", unique: true + end + + create_table "oauth_applications", id: :serial, force: :cascade do |t| + t.string "name", null: false + t.string "uid", null: false + t.string "secret", null: false + t.text "redirect_uri", null: false + t.string "scopes", default: "", null: false + t.datetime "created_at" + t.datetime "updated_at" + t.integer "owner_id" + t.string "owner_type" + t.boolean "confidential", default: true, null: false + t.index ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type" + t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true + end + + create_table "openstax_accounts_accounts", id: :serial, force: :cascade do |t| + t.integer "openstax_uid" + t.string "username" + t.string "access_token" + t.string "first_name" + t.string "last_name" + t.string "full_name" + t.string "title" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "faculty_status", default: 0, null: false + t.string "salesforce_contact_id" + t.uuid "uuid", default: -> { "gen_random_uuid()" }, null: false + t.integer "role", default: 0, null: false + t.citext "support_identifier" + t.boolean "is_test" + t.integer "school_type", default: 0, null: false + t.index ["access_token"], name: "index_openstax_accounts_accounts_on_access_token", unique: true + t.index ["faculty_status"], name: "index_openstax_accounts_accounts_on_faculty_status" + t.index ["first_name"], name: "index_openstax_accounts_accounts_on_first_name" + t.index ["full_name"], name: "index_openstax_accounts_accounts_on_full_name" + t.index ["last_name"], name: "index_openstax_accounts_accounts_on_last_name" + t.index ["openstax_uid"], name: "index_openstax_accounts_accounts_on_openstax_uid", unique: true + t.index ["role"], name: "index_openstax_accounts_accounts_on_role" + t.index ["salesforce_contact_id"], name: "index_openstax_accounts_accounts_on_salesforce_contact_id" + t.index ["school_type"], name: "index_openstax_accounts_accounts_on_school_type" + t.index ["support_identifier"], name: "index_openstax_accounts_accounts_on_support_identifier", unique: true + t.index ["username"], name: "index_openstax_accounts_accounts_on_username", unique: true + t.index ["uuid"], name: "index_openstax_accounts_accounts_on_uuid", unique: true + end + + create_table "openstax_accounts_group_members", id: :serial, force: :cascade do |t| + t.integer "group_id", null: false + t.integer "user_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["group_id", "user_id"], name: "index_openstax_accounts_group_members_on_group_id_and_user_id", unique: true + t.index ["user_id"], name: "index_openstax_accounts_group_members_on_user_id" end - add_index "oauth_access_grants", ["token"], name: "index_oauth_access_grants_on_token", unique: true, using: :btree + create_table "openstax_accounts_group_nestings", id: :serial, force: :cascade do |t| + t.integer "member_group_id", null: false + t.integer "container_group_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["container_group_id"], name: "index_openstax_accounts_group_nestings_on_container_group_id" + t.index ["member_group_id"], name: "index_openstax_accounts_group_nestings_on_member_group_id", unique: true + end - create_table "oauth_access_tokens", force: :cascade do |t| - t.integer "resource_owner_id" - t.integer "application_id" - t.string "token", null: false - t.string "refresh_token" - t.integer "expires_in" - t.datetime "revoked_at" - t.datetime "created_at", null: false - t.string "scopes" - t.string "previous_refresh_token", default: "", null: false + create_table "openstax_accounts_group_owners", id: :serial, force: :cascade do |t| + t.integer "group_id", null: false + t.integer "user_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["group_id", "user_id"], name: "index_openstax_accounts_group_owners_on_group_id_and_user_id", unique: true + t.index ["user_id"], name: "index_openstax_accounts_group_owners_on_user_id" end - add_index "oauth_access_tokens", ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true, using: :btree - add_index "oauth_access_tokens", ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id", using: :btree - add_index "oauth_access_tokens", ["token"], name: "index_oauth_access_tokens_on_token", unique: true, using: :btree + create_table "openstax_accounts_groups", id: :serial, force: :cascade do |t| + t.integer "openstax_uid", null: false + t.boolean "is_public", default: false, null: false + t.string "name" + t.text "cached_subtree_group_ids" + t.text "cached_supertree_group_ids" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["is_public"], name: "index_openstax_accounts_groups_on_is_public" + t.index ["openstax_uid"], name: "index_openstax_accounts_groups_on_openstax_uid", unique: true + end - create_table "oauth_applications", force: :cascade do |t| - t.string "name", null: false - t.string "uid", null: false - t.string "secret", null: false - t.text "redirect_uri", null: false - t.string "scopes", default: "", null: false - t.datetime "created_at" - t.datetime "updated_at" - t.integer "owner_id" - t.string "owner_type" - t.boolean "confidential", default: true, null: false - end - - add_index "oauth_applications", ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type", using: :btree - add_index "oauth_applications", ["uid"], name: "index_oauth_applications_on_uid", unique: true, using: :btree - - create_table "openstax_accounts_accounts", force: :cascade do |t| - t.integer "openstax_uid" - t.string "username" - t.string "access_token" - t.string "first_name" - t.string "last_name" - t.string "full_name" - t.string "title" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "faculty_status", default: 0, null: false - t.string "salesforce_contact_id" - t.uuid "uuid", default: "gen_random_uuid()", null: false - t.integer "role", default: 0, null: false - t.citext "support_identifier" - t.boolean "is_test" - end - - add_index "openstax_accounts_accounts", ["access_token"], name: "index_openstax_accounts_accounts_on_access_token", unique: true, using: :btree - add_index "openstax_accounts_accounts", ["faculty_status"], name: "index_openstax_accounts_accounts_on_faculty_status", using: :btree - add_index "openstax_accounts_accounts", ["first_name"], name: "index_openstax_accounts_accounts_on_first_name", using: :btree - add_index "openstax_accounts_accounts", ["full_name"], name: "index_openstax_accounts_accounts_on_full_name", using: :btree - add_index "openstax_accounts_accounts", ["last_name"], name: "index_openstax_accounts_accounts_on_last_name", using: :btree - add_index "openstax_accounts_accounts", ["openstax_uid"], name: "index_openstax_accounts_accounts_on_openstax_uid", unique: true, using: :btree - add_index "openstax_accounts_accounts", ["role"], name: "index_openstax_accounts_accounts_on_role", using: :btree - add_index "openstax_accounts_accounts", ["salesforce_contact_id"], name: "index_openstax_accounts_accounts_on_salesforce_contact_id", using: :btree - add_index "openstax_accounts_accounts", ["support_identifier"], name: "index_openstax_accounts_accounts_on_support_identifier", unique: true, using: :btree - add_index "openstax_accounts_accounts", ["username"], name: "index_openstax_accounts_accounts_on_username", unique: true, using: :btree - add_index "openstax_accounts_accounts", ["uuid"], name: "index_openstax_accounts_accounts_on_uuid", unique: true, using: :btree - - create_table "openstax_accounts_group_members", force: :cascade do |t| - t.integer "group_id", null: false - t.integer "user_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - end - - add_index "openstax_accounts_group_members", ["group_id", "user_id"], name: "index_openstax_accounts_group_members_on_group_id_and_user_id", unique: true, using: :btree - add_index "openstax_accounts_group_members", ["user_id"], name: "index_openstax_accounts_group_members_on_user_id", using: :btree - - create_table "openstax_accounts_group_nestings", force: :cascade do |t| - t.integer "member_group_id", null: false - t.integer "container_group_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - end - - add_index "openstax_accounts_group_nestings", ["container_group_id"], name: "index_openstax_accounts_group_nestings_on_container_group_id", using: :btree - add_index "openstax_accounts_group_nestings", ["member_group_id"], name: "index_openstax_accounts_group_nestings_on_member_group_id", unique: true, using: :btree - - create_table "openstax_accounts_group_owners", force: :cascade do |t| - t.integer "group_id", null: false - t.integer "user_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - end - - add_index "openstax_accounts_group_owners", ["group_id", "user_id"], name: "index_openstax_accounts_group_owners_on_group_id_and_user_id", unique: true, using: :btree - add_index "openstax_accounts_group_owners", ["user_id"], name: "index_openstax_accounts_group_owners_on_user_id", using: :btree - - create_table "openstax_accounts_groups", force: :cascade do |t| - t.integer "openstax_uid", null: false - t.boolean "is_public", default: false, null: false - t.string "name" - t.text "cached_subtree_group_ids" - t.text "cached_supertree_group_ids" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - end - - add_index "openstax_accounts_groups", ["is_public"], name: "index_openstax_accounts_groups_on_is_public", using: :btree - add_index "openstax_accounts_groups", ["openstax_uid"], name: "index_openstax_accounts_groups_on_openstax_uid", unique: true, using: :btree - - create_table "publication_groups", force: :cascade do |t| - t.string "publishable_type", null: false - t.integer "number", null: false - t.uuid "uuid", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "latest_version", null: false - t.integer "latest_published_version" - t.string "nickname" - end - - add_index "publication_groups", ["id", "latest_published_version"], name: "index_publication_groups_on_id_and_latest_published_version", using: :btree - add_index "publication_groups", ["id", "latest_version"], name: "index_publication_groups_on_id_and_latest_version", using: :btree - add_index "publication_groups", ["nickname"], name: "index_publication_groups_on_nickname", unique: true, using: :btree - add_index "publication_groups", ["number", "publishable_type"], name: "index_publication_groups_on_number_and_publishable_type", unique: true, using: :btree - add_index "publication_groups", ["publishable_type"], name: "index_publication_groups_on_publishable_type", using: :btree - add_index "publication_groups", ["uuid"], name: "index_publication_groups_on_uuid", unique: true, using: :btree - - create_table "publications", force: :cascade do |t| - t.integer "publishable_id", null: false - t.string "publishable_type", null: false - t.integer "license_id" - t.integer "version", null: false + create_table "publication_groups", id: :serial, force: :cascade do |t| + t.string "publishable_type", null: false + t.integer "number", null: false + t.uuid "uuid", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "latest_version", null: false + t.integer "latest_published_version" + t.string "nickname" + t.index ["id", "latest_published_version"], name: "index_publication_groups_on_id_and_latest_published_version" + t.index ["id", "latest_version"], name: "index_publication_groups_on_id_and_latest_version" + t.index ["nickname"], name: "index_publication_groups_on_nickname", unique: true + t.index ["number", "publishable_type"], name: "index_publication_groups_on_number_and_publishable_type", unique: true + t.index ["publishable_type"], name: "index_publication_groups_on_publishable_type" + t.index ["uuid"], name: "index_publication_groups_on_uuid", unique: true + end + + create_table "publications", id: :serial, force: :cascade do |t| + t.integer "publishable_id", null: false + t.string "publishable_type", null: false + t.integer "license_id" + t.integer "version", null: false t.datetime "published_at" t.datetime "yanked_at" t.datetime "embargoed_until" - t.boolean "embargo_children_only", default: false, null: false - t.boolean "major_change", default: false, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "publication_group_id", null: false - t.uuid "uuid", null: false - end - - add_index "publications", ["embargoed_until"], name: "index_publications_on_embargoed_until", using: :btree - add_index "publications", ["license_id"], name: "index_publications_on_license_id", using: :btree - add_index "publications", ["publication_group_id", "version"], name: "index_publications_on_publication_group_id_and_version", using: :btree - add_index "publications", ["publishable_id", "publishable_type"], name: "index_publications_on_publishable_id_and_publishable_type", unique: true, using: :btree - add_index "publications", ["published_at"], name: "index_publications_on_published_at", using: :btree - add_index "publications", ["uuid"], name: "index_publications_on_uuid", unique: true, using: :btree - add_index "publications", ["yanked_at"], name: "index_publications_on_yanked_at", using: :btree - - create_table "question_dependencies", force: :cascade do |t| - t.integer "parent_question_id", null: false - t.integer "dependent_question_id", null: false - t.boolean "is_optional", default: false, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.boolean "embargo_children_only", default: false, null: false + t.boolean "major_change", default: false, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "publication_group_id", null: false + t.uuid "uuid", null: false + t.index ["embargoed_until"], name: "index_publications_on_embargoed_until" + t.index ["license_id"], name: "index_publications_on_license_id" + t.index ["publication_group_id", "version"], name: "index_publications_on_publication_group_id_and_version" + t.index ["publishable_id", "publishable_type"], name: "index_publications_on_publishable_id_and_publishable_type", unique: true + t.index ["published_at"], name: "index_publications_on_published_at" + t.index ["uuid"], name: "index_publications_on_uuid", unique: true + t.index ["yanked_at"], name: "index_publications_on_yanked_at" + end + + create_table "question_dependencies", id: :serial, force: :cascade do |t| + t.integer "parent_question_id", null: false + t.integer "dependent_question_id", null: false + t.boolean "is_optional", default: false, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["dependent_question_id", "parent_question_id"], name: "index_question_dependencies_on_dependent_q_id_and_parent_q_id", unique: true + t.index ["parent_question_id"], name: "index_question_dependencies_on_parent_question_id" end - add_index "question_dependencies", ["dependent_question_id", "parent_question_id"], name: "index_question_dependencies_on_dependent_q_id_and_parent_q_id", unique: true, using: :btree - add_index "question_dependencies", ["parent_question_id"], name: "index_question_dependencies_on_parent_question_id", using: :btree - - create_table "questions", force: :cascade do |t| - t.integer "exercise_id", null: false - t.text "stimulus" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.boolean "answer_order_matters", default: false, null: false - t.integer "sort_position", null: false + create_table "questions", id: :serial, force: :cascade do |t| + t.integer "exercise_id", null: false + t.text "stimulus" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "answer_order_matters", default: false, null: false + t.integer "sort_position", null: false + t.index ["exercise_id", "sort_position"], name: "index_questions_on_exercise_id_and_sort_position", unique: true end - add_index "questions", ["exercise_id", "sort_position"], name: "index_questions_on_exercise_id_and_sort_position", unique: true, using: :btree - - create_table "stem_answers", force: :cascade do |t| - t.integer "stem_id", null: false - t.integer "answer_id", null: false - t.decimal "correctness", precision: 3, scale: 2, default: 0.0, null: false - t.text "feedback" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "stem_answers", id: :serial, force: :cascade do |t| + t.integer "stem_id", null: false + t.integer "answer_id", null: false + t.decimal "correctness", precision: 3, scale: 2, default: "0.0", null: false + t.text "feedback" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["answer_id", "stem_id"], name: "index_stem_answers_on_answer_id_and_stem_id", unique: true + t.index ["stem_id", "correctness"], name: "index_stem_answers_on_stem_id_and_correctness" end - add_index "stem_answers", ["answer_id", "stem_id"], name: "index_stem_answers_on_answer_id_and_stem_id", unique: true, using: :btree - add_index "stem_answers", ["stem_id", "correctness"], name: "index_stem_answers_on_stem_id_and_correctness", using: :btree - - create_table "stems", force: :cascade do |t| - t.integer "question_id", null: false - t.text "content", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "stems", id: :serial, force: :cascade do |t| + t.integer "question_id", null: false + t.text "content", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["question_id"], name: "index_stems_on_question_id" end - add_index "stems", ["question_id"], name: "index_stems_on_question_id", using: :btree - - create_table "stylings", force: :cascade do |t| - t.integer "stylable_id", null: false - t.string "stylable_type", null: false - t.string "style", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "stylings", id: :serial, force: :cascade do |t| + t.integer "stylable_id", null: false + t.string "stylable_type", null: false + t.string "style", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["stylable_id", "stylable_type", "style"], name: "index_stylings_on_stylable_id_and_stylable_type_and_style", unique: true end - add_index "stylings", ["stylable_id", "stylable_type", "style"], name: "index_stylings_on_stylable_id_and_stylable_type_and_style", unique: true, using: :btree - - create_table "tags", force: :cascade do |t| - t.string "name", null: false + create_table "tags", id: :serial, force: :cascade do |t| + t.string "name", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.index ["name"], name: "index_tags_on_name", unique: true end - add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree - - create_table "trusted_applications", force: :cascade do |t| - t.integer "application_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "trusted_applications", id: :serial, force: :cascade do |t| + t.integer "application_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["application_id"], name: "index_trusted_applications_on_application_id", unique: true end - add_index "trusted_applications", ["application_id"], name: "index_trusted_applications_on_application_id", unique: true, using: :btree - - create_table "users", force: :cascade do |t| - t.integer "account_id", null: false + create_table "users", id: :serial, force: :cascade do |t| + t.integer "account_id", null: false t.datetime "deleted_at" - t.boolean "show_public_domain_attribution", default: true, null: false - t.boolean "forward_notifications_to_deputies", default: false, null: false - t.boolean "receive_role_notifications", default: true, null: false - t.boolean "receive_access_notifications", default: true, null: false - t.boolean "receive_comment_notifications", default: true, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - end - - add_index "users", ["account_id"], name: "index_users_on_account_id", unique: true, using: :btree - add_index "users", ["deleted_at"], name: "index_users_on_deleted_at", using: :btree - - create_table "vocab_distractors", force: :cascade do |t| - t.integer "vocab_term_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "distractor_publication_group_id", null: false + t.boolean "show_public_domain_attribution", default: true, null: false + t.boolean "forward_notifications_to_deputies", default: false, null: false + t.boolean "receive_role_notifications", default: true, null: false + t.boolean "receive_access_notifications", default: true, null: false + t.boolean "receive_comment_notifications", default: true, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["account_id"], name: "index_users_on_account_id", unique: true + t.index ["deleted_at"], name: "index_users_on_deleted_at" end - add_index "vocab_distractors", ["distractor_publication_group_id"], name: "index_vocab_distractors_on_distractor_publication_group_id", using: :btree - add_index "vocab_distractors", ["vocab_term_id", "distractor_publication_group_id"], name: "index_vocab_distractors_on_v_t_id_and_d_p_g_id", unique: true, using: :btree - - create_table "vocab_term_tags", force: :cascade do |t| - t.integer "vocab_term_id" - t.integer "tag_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "vocab_distractors", id: :serial, force: :cascade do |t| + t.integer "vocab_term_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "distractor_publication_group_id", null: false + t.index ["distractor_publication_group_id"], name: "index_vocab_distractors_on_distractor_publication_group_id" + t.index ["vocab_term_id", "distractor_publication_group_id"], name: "index_vocab_distractors_on_v_t_id_and_d_p_g_id", unique: true end - add_index "vocab_term_tags", ["tag_id"], name: "index_vocab_term_tags_on_tag_id", using: :btree - add_index "vocab_term_tags", ["vocab_term_id", "tag_id"], name: "index_vocab_term_tags_on_vocab_term_id_and_tag_id", unique: true, using: :btree - - create_table "vocab_terms", force: :cascade do |t| - t.string "name", null: false - t.string "definition", default: "", null: false - t.string "distractor_literals", default: [], null: false, array: true - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "vocab_term_tags", id: :serial, force: :cascade do |t| + t.integer "vocab_term_id" + t.integer "tag_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["tag_id"], name: "index_vocab_term_tags_on_tag_id" + t.index ["vocab_term_id", "tag_id"], name: "index_vocab_term_tags_on_vocab_term_id_and_tag_id", unique: true end - add_index "vocab_terms", ["definition"], name: "index_vocab_terms_on_definition", using: :btree - add_index "vocab_terms", ["name", "definition"], name: "index_vocab_terms_on_name_and_definition", using: :btree - - create_table "votes", force: :cascade do |t| - t.integer "votable_id" - t.string "votable_type" - t.integer "voter_id" - t.string "voter_type" - t.boolean "vote_flag" - t.string "vote_scope" - t.integer "vote_weight" + create_table "vocab_terms", id: :serial, force: :cascade do |t| + t.string "name", null: false + t.string "definition", default: "", null: false + t.string "distractor_literals", default: [], null: false, array: true + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["definition"], name: "index_vocab_terms_on_definition" + t.index ["name", "definition"], name: "index_vocab_terms_on_name_and_definition" + end + + create_table "votes", id: :serial, force: :cascade do |t| + t.integer "votable_id" + t.string "votable_type" + t.integer "voter_id" + t.string "voter_type" + t.boolean "vote_flag" + t.string "vote_scope" + t.integer "vote_weight" t.datetime "created_at" t.datetime "updated_at" + t.index ["votable_id", "votable_type", "vote_scope"], name: "index_votes_on_votable_id_and_votable_type_and_vote_scope" + t.index ["voter_id", "voter_type", "vote_scope"], name: "index_votes_on_voter_id_and_voter_type_and_vote_scope" end - add_index "votes", ["votable_id", "votable_type", "vote_scope"], name: "index_votes_on_votable_id_and_votable_type_and_vote_scope", using: :btree - add_index "votes", ["voter_id", "voter_type", "vote_scope"], name: "index_votes_on_voter_id_and_voter_type_and_vote_scope", using: :btree - add_foreign_key "exercise_tags", "exercises", on_update: :cascade, on_delete: :cascade add_foreign_key "exercise_tags", "tags", on_update: :cascade, on_delete: :cascade add_foreign_key "list_publication_groups", "lists" diff --git a/lib/active_record/calculations_patch.rb b/lib/active_record/calculations_patch.rb deleted file mode 100644 index 3ff7ed95..00000000 --- a/lib/active_record/calculations_patch.rb +++ /dev/null @@ -1,31 +0,0 @@ -# Due to weird interactions between Squeel and ActiveRecord, -# we need this patch to be able to use .count in the exercises search -# Otherwise, the grep method call will throw an exception and the count will fail -# https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/calculations.rb -ActiveRecord::Calculations.class_exec do - private - - def perform_calculation(operation, column_name, options = {}) - operation = operation.to_s.downcase - - # If #count is used with #distinct / #uniq it is considered distinct. - # (eg. relation.distinct.count) - distinct = self.distinct_value - - if operation == "count" - column_name ||= select_for_count - - outer_join = !arel.ast.grep(Arel::Nodes::OuterJoin).empty? rescue true - distinct = true if outer_join - - column_name = primary_key if column_name == :all && distinct - distinct = nil if column_name =~ /\s*DISTINCT[\s(]+/i - end - - if group_values.any? - execute_grouped_calculation(operation, column_name, distinct) - else - execute_simple_calculation(operation, column_name, distinct) - end - end -end diff --git a/lib/active_record/table_association_name_patch.rb b/lib/active_record/table_association_name_patch.rb new file mode 100644 index 00000000..cbe61c23 --- /dev/null +++ b/lib/active_record/table_association_name_patch.rb @@ -0,0 +1,23 @@ +# https://github.com/rails/rails/issues/32374#issuecomment-378122738 +module ActiveRecord + class TableMetadata + + def associated_table(table_name) + association = klass._reflect_on_association(table_name) || klass._reflect_on_association(table_name.to_s.singularize) + + if !association && table_name == arel_table.name + return self + elsif association && !association.polymorphic? + association_klass = association.klass + arel_table = association_klass.arel_table + else + type_caster = TypeCaster::Connection.new(klass, table_name) + association_klass = nil + arel_table = Arel::Table.new(table_name, type_caster: type_caster) + end + + TableMetadata.new(association_klass, arel_table, association) + end + + end +end diff --git a/lib/exercises/importer.rb b/lib/exercises/importer.rb index ef0d8ba6..ee9672a4 100644 --- a/lib/exercises/importer.rb +++ b/lib/exercises/importer.rb @@ -12,7 +12,7 @@ def parse(text, exercise) text = text.to_s - kd = Kramdown::Document.new(text.to_s.strip, attachable: exercise) + kd = Kramdown::Document.new(text.to_s.strip, math_engine: :openstax, attachable: exercise) # If only one

    tag, remove it and just return the nodes below kd.root.children = kd.root.children.first.children \ if kd.root.children.length == 1 && kd.root.children.first.type == :p @@ -51,10 +51,14 @@ def import_row(row, row_number) ex.tags = book_tags + lo_tags + type_tags + \ [id_tag, cnxmod_tag, dok_tag, blooms_tag, time_tag] + pub = Publication.arel_table + pubg = PublicationGroup.arel_table + latest_exercise = Exercise - .joins([{publication: :publication_group}, {exercise_tags: :tag}]) - .where(exercise_tags: {tag: {name: id_tag}}) - .order {[publication.publication_group.number.desc, publication.version.desc]}.first + .joins([{publication: :publication_group}, {exercise_tags: :tag}]) + .where(exercise_tags: {tag: {name: id_tag}}) + .order([pubg[:number].desc, pub[:version].desc]).first + unless latest_exercise.nil? ex.publication.publication_group = latest_exercise.publication.publication_group diff --git a/lib/publishable/active_record.rb b/lib/publishable/active_record.rb index 5a400ee6..af2abf54 100644 --- a/lib/publishable/active_record.rb +++ b/lib/publishable/active_record.rb @@ -20,29 +20,31 @@ def publishable(options = {}) to: :publication scope :published, -> do - joins(:publication).where.not(publications: { published_at: nil }) + joins(:publication).where.not(publication: { published_at: nil }) end - scope :unpublished, -> { joins(:publication).where(publications: { published_at: nil }) } + scope :unpublished, -> { joins(:publication).where(publication: { published_at: nil }) } scope :with_id, ->(id) do nn, vv = id.to_s.split('@') - joins(publication: :publication_group).where do - wheres = (publication.publication_group.uuid == nn) | - (publication.publication_group.number == nn) + pub = Publication.arel_table + pubg = PublicationGroup.arel_table - case vv + wheres = pubg[:uuid].eq(nn).or(pubg[:number].eq(nn)) + case vv when NilClass - (wheres | (publication.uuid == nn)) & (publication.published_at != nil) + wheres = wheres.or(pub[:uuid].eq(nn)).and(pub[:published_at].not_eq(nil)) when 'draft', 'd' - wheres & (publication.published_at == nil) + wheres = wheres.and(pub[:published_at].eq(nil)) when 'latest' wheres else - wheres & (publication.version == vv) - end - end.order { [publication.publication_group.number.asc, publication.version.desc] } + wheres = wheres.and(pub[:version].eq(vv)) + end + + joins(publication: :publication_group).where(wheres + ).order( [pubg[:number].asc, pub[:version].desc] ) end scope :visible_for, ->(options) do @@ -54,22 +56,33 @@ def publishable(options = {}) next all if user.administrator user_id = user.id - joins do - [ - publication.authors, - publication.copyright_holders, - publication.publication_group.list_publication_groups.outer.list.outer.list_owners, - publication.publication_group.list_publication_groups.outer.list.outer.list_editors, - publication.publication_group.list_publication_groups.outer.list.outer.list_readers - ].map(&:outer) - end.where do - (publication.published_at != nil ) | - (authors.user_id == user_id ) | - (copyright_holders.user_id == user_id ) | - ((list_owners.owner_id == user_id) & (list_owners.owner_type == 'User')) | - ((list_editors.editor_id == user_id) & (list_editors.editor_type == 'User')) | - ((list_readers.reader_id == user_id) & (list_readers.reader_type == 'User')) - end + pub = Publication.arel_table + au = Author.arel_table + cw = CopyrightHolder.arel_table + pubg = PublicationGroup.arel_table + lpg = ListPublicationGroup.arel_table + l_own = ListOwner.arel_table + l_edit = ListEditor.arel_table + l_read = ListReader.arel_table + + me = self.arel_table + + joins(me.join(pub).on(pub[:publishable_id].eq(me[:id]), pub[:publishable_type].eq(self.name)) + .join(au).on(au[:publication_id].eq(pub[:id])) + .join(cw).on(cw[:publication_id].eq(pub[:id])) + .join(pubg).on(pub[:publication_group_id].eq(pubg[:id])) + .outer_join(lpg).on(lpg[:publication_group_id].eq(pubg[:id])) + .outer_join(l_own).on(l_own[:list_id].eq(lpg[:id])) + .outer_join(l_edit).on(l_edit[:list_id].eq(lpg[:id])) + .outer_join(l_read).on(l_read[:list_id].eq(lpg[:id])).join_sources + ).where( + pub[:published_at].not_eq(nil) + .or(au[:user_id].eq(user_id)) + .or(cw[:user_id].eq(user_id)) + .or(l_own[:owner_id].eq(user_id).and(l_own[:owner_type].eq('User'))) + .or(l_edit[:editor_id].eq(user_id).and(l_edit[:editor_type].eq('User'))) + .or(l_read[:reader_id].eq(user_id).and(l_read[:reader_type].eq('User')))) + end # By default, returns both the latest published version and the latest draft, if any diff --git a/lib/tasks/vocab_terms/unlink.rake b/lib/tasks/vocab_terms/unlink.rake index ad787cfa..2acdef66 100644 --- a/lib/tasks/vocab_terms/unlink.rake +++ b/lib/tasks/vocab_terms/unlink.rake @@ -1,7 +1,7 @@ namespace :vocab_terms do desc 'unlinks all vocab terms that are currently linked to other terms' task unlink: :environment do - VocabTerm.joins(:vocab_distractors).latest.uniq.find_in_batches do |vocab_terms| + VocabTerm.joins(:vocab_distractors).latest.distinct.find_in_batches do |vocab_terms| VocabTerm.transaction do vocab_terms.each do |vocab_term| vocab_term = vocab_term.new_version if vocab_term.is_published? diff --git a/lib/user_html.rb b/lib/user_html.rb index 54e6572a..5768cd89 100644 --- a/lib/user_html.rb +++ b/lib/user_html.rb @@ -10,7 +10,7 @@ module ActiveRecord module Base def user_html(*attributes) attributes.each do |attribute| - filter_name = "link_and_sanitize_#{attribute.to_s}" + filter_name = :"link_and_sanitize_#{attribute.to_s}" class_exec do before_validation filter_name diff --git a/lib/vocab_terms/importer.rb b/lib/vocab_terms/importer.rb index cb009e52..39a1f323 100644 --- a/lib/vocab_terms/importer.rb +++ b/lib/vocab_terms/importer.rb @@ -54,11 +54,10 @@ def import_row(row, row_number) @latest_term_map ||= Hash.new do |hash, chapter| hash[chapter] = Hash.new do |hash, name| lo_like = "lo:stax-#{book}:#{chapter}-%" - hash[name] = VocabTerm - .joins([{publication: :publication_group}, {vocab_term_tags: :tag}]) - .where(name: name) - .where {vocab_term_tags.tag.name.like lo_like} - .order {[publication.publication_group.number.desc, publication.version.desc]}.first + ta = Tag.arel_table + pub = Publication.arel_table + pubg = PublicationGroup.arel_table + hash[name] = VocabTerm.joins([{publication: :publication_group}, {vocab_term_tags: :tag}]).where(name: name).where(ta[:name].matches lo_like).order([pubg[:number].desc, pub[:version].desc]).first end end diff --git a/spec/access_policies/doorkeeper/application_access_policy_spec.rb b/spec/access_policies/doorkeeper/application_access_policy_spec.rb index 9ce63228..142bdf43 100644 --- a/spec/access_policies/doorkeeper/application_access_policy_spec.rb +++ b/spec/access_policies/doorkeeper/application_access_policy_spec.rb @@ -4,7 +4,7 @@ let(:anon) { AnonymousUser.instance } let(:user) { FactoryBot.create(:user) } let(:admin) { FactoryBot.create(:user, :administrator) } - let(:app) { FactoryBot.build(:doorkeeper_application) } + let(:app) { FactoryBot.create(:doorkeeper_application) } let(:another_app) { FactoryBot.create(:doorkeeper_application) } context 'read, update' do diff --git a/spec/controllers/admin/administrators_controller_spec.rb b/spec/controllers/admin/administrators_controller_spec.rb index e7b6f367..49f4e370 100644 --- a/spec/controllers/admin/administrators_controller_spec.rb +++ b/spec/controllers/admin/administrators_controller_spec.rb @@ -35,7 +35,7 @@ module Admin context 'for anonymous' do it 'redirects to the login page' do - expect{ post :create, valid_params }.not_to change{ Administrator.count } + expect{ post :create, params: valid_params }.not_to change{ Administrator.count } expect(response).to redirect_to(controller.openstax_accounts.login_path) end end @@ -43,14 +43,14 @@ module Admin context 'for non-admins' do it 'raises SecurityTransgression' do controller.sign_in user - expect{ post :create, valid_params }.to raise_error(SecurityTransgression) + expect{ post :create, params: valid_params }.to raise_error(SecurityTransgression) end end context 'for admins' do it 'makes the given user an administrator' do controller.sign_in admin - expect{ post :create, valid_params }.to change{ Administrator.count }.by(1) + expect{ post :create, params: valid_params }.to change{ Administrator.count }.by(1) expect(response).to redirect_to(admin_administrators_path) expect(user.reload.is_administrator?).to eq true end @@ -62,7 +62,7 @@ module Admin context 'for anonymous' do it 'redirects to the login page' do - expect{ delete :destroy, valid_params }.not_to change{ Administrator.count } + expect{ delete :destroy, params: valid_params }.not_to change{ Administrator.count } expect(response).to redirect_to(controller.openstax_accounts.login_path) end end @@ -70,14 +70,14 @@ module Admin context 'for non-admins' do it 'raises SecurityTransgression' do controller.sign_in user - expect{ delete :destroy, valid_params }.to raise_error(SecurityTransgression) + expect{ delete :destroy, params: valid_params }.to raise_error(SecurityTransgression) end end context 'for admins' do it 'deletes the given administrator' do controller.sign_in admin - expect{ delete :destroy, valid_params }.to change{ Administrator.count }.by(-1) + expect{ delete :destroy, params: valid_params }.to change{ Administrator.count }.by(-1) expect(response).to redirect_to(admin_administrators_path) expect(admin.reload.is_administrator?).to eq false end diff --git a/spec/controllers/admin/console_controller_spec.rb b/spec/controllers/admin/console_controller_spec.rb index 57e9cc72..388cd948 100644 --- a/spec/controllers/admin/console_controller_spec.rb +++ b/spec/controllers/admin/console_controller_spec.rb @@ -9,7 +9,7 @@ module Admin describe 'GET index' do context 'for anonymous' do it 'redirects to the login page' do - xhr :get, :index + get :index, xhr: true expect(response).to have_http_status(:forbidden) end end @@ -17,14 +17,14 @@ module Admin context 'for non-admins' do it 'raises SecurityTransgression' do controller.sign_in user - expect{ xhr :get, :index }.to raise_error(SecurityTransgression) + expect{ get :index, xhr: true }.to raise_error(SecurityTransgression) end end context 'for admins' do it 'returns http ok' do controller.sign_in admin - xhr :get, :index + get :index, xhr: true expect(response).to have_http_status(:ok) end end diff --git a/spec/controllers/admin/exceptions_controller_spec.rb b/spec/controllers/admin/exceptions_controller_spec.rb index f70204bb..dc6f31e8 100644 --- a/spec/controllers/admin/exceptions_controller_spec.rb +++ b/spec/controllers/admin/exceptions_controller_spec.rb @@ -6,7 +6,6 @@ module Admin EXCEPTIONS = [[SecurityTransgression], [ActiveRecord::RecordNotFound], [ActionController::RoutingError, '/blah/blah/blah'.inspect], - [ActionController::UnknownController], [AbstractController::ActionNotFound], [ActionView::MissingTemplate, [['a', 'b'], 'path', ['pre1', 'pre2'], @@ -21,7 +20,7 @@ module Admin context 'for anonymous' do it 'returns 403 forbidden' do EXCEPTIONS.each do |klass, args| - xhr :get, :show, id: klass.name, args: args + get :show, params: { id: klass.name, args: args }, xhr: true expect(response).to have_http_status(:forbidden) end end @@ -31,7 +30,7 @@ module Admin it 'raises SecurityTransgression' do controller.sign_in user EXCEPTIONS.each do |klass, args| - expect{ xhr :get, :show, id: klass.name, args: args }.to( + expect{ get :show, params: { id: klass.name, args: args }, xhr: true }.to( raise_error(SecurityTransgression) ) end @@ -42,7 +41,7 @@ module Admin it 'raises the given exception' do controller.sign_in admin EXCEPTIONS.each do |klass, args| - expect{ xhr :get, :show, id: klass.name, args: args }.to raise_error(klass) + expect{ get :show, params: { id: klass.name, args: args }, xhr: true }.to raise_error(klass) end end end diff --git a/spec/controllers/api/v1/attachments_controller_spec.rb b/spec/controllers/api/v1/attachments_controller_spec.rb index 3afc0fdd..24321051 100644 --- a/spec/controllers/api/v1/attachments_controller_spec.rb +++ b/spec/controllers/api/v1/attachments_controller_spec.rb @@ -28,6 +28,9 @@ module Api::V1 exercise.publication.authors << FactoryBot.build( :author, user: user, publication: exercise.publication ) + exercise.publication.copyright_holders << FactoryBot.build( + :copyright_holder, user: user, publication: exercise.publication + ) exercise.save! exercise end @@ -37,16 +40,13 @@ module Api::V1 context "POST create" do let(:image) { - image = ActionDispatch::Http::UploadedFile.new( - filename: 'test_photo_1.jpg', - type: 'image/jpeg', - tempfile: File.new("#{Rails.root}/spec/fixtures/rails.png") - ) + image = Rack::Test::UploadedFile.new("#{Rails.root}/spec/fixtures/rails.png", + 'image/jpeg') } it 'attaches a file to an exercise' do expect do - api_post :create, user_token, parameters: { exercise_id: exercise_id, file: image } + api_post :create, user_token, params: { exercise_id: exercise_id, file: image } end.to change{ exercise.attachments.count }.by(1) expect(response).to have_http_status(:success) end @@ -54,7 +54,7 @@ module Api::V1 it 'creates a draft if needed' do exercise.publication.publish.save! expect do - api_post :create, user_token, parameters: { exercise_id: exercise_id, file: image } + api_post :create, user_token, params: { exercise_id: exercise_id, file: image } end.to change{ exercise.publication_group.reload.latest_version }.from(1).to(2) expect(response).to have_http_status(:success) end @@ -68,7 +68,7 @@ module Api::V1 ).outputs[:attachment] expect do - api_delete :destroy, user_token, parameters: { + api_delete :destroy, user_token, params: { exercise_id: exercise_id, filename: attachment.read_attribute(:asset) } end.to change(Attachment, :count).by(-1) diff --git a/spec/controllers/api/v1/community_solutions_controller_spec.rb b/spec/controllers/api/v1/community_solutions_controller_spec.rb index 7f243393..cb78dd08 100644 --- a/spec/controllers/api/v1/community_solutions_controller_spec.rb +++ b/spec/controllers/api/v1/community_solutions_controller_spec.rb @@ -11,7 +11,7 @@ module Api::V1 context "GET index" do it "assigns all solutions as @solutions" do solution = CommunitySolution.create! valid_attributes - get :index, {}, valid_session + get :index, session: valid_session expect(assigns(:solutions)).to eq([solution]) end end @@ -19,7 +19,7 @@ module Api::V1 context "GET show" do it "assigns the requested solution as @solution" do solution = CommunitySolution.create! valid_attributes - get :show, {id: solution.to_param}, valid_session + get :show, params: { id: solution.to_param }, session: valid_session expect(assigns(:solution)).to eq(solution) end end @@ -28,18 +28,18 @@ module Api::V1 context "with valid params" do it "creates a new CommunitySolution" do expect { - post :create, {solution: valid_attributes}, valid_session + post :create, params: { solution: valid_attributes }, session: valid_session }.to change(CommunitySolution, :count).by(1) end it "assigns a newly created solution as @solution" do - post :create, {solution: valid_attributes}, valid_session + post :create, params: { solution: valid_attributes }, session: valid_session expect(assigns(:solution)).to be_a(CommunitySolution) expect(assigns(:solution)).to be_persisted end it "redirects to the created solution" do - post :create, {solution: valid_attributes}, valid_session + post :create, params: { solution: valid_attributes }, session: valid_session expect(response).to redirect_to(CommunitySolution.last) end end @@ -48,14 +48,14 @@ module Api::V1 it "assigns a newly created but unsaved solution as @solution" do # Trigger the behavior that occurs when invalid params are submitted CommunitySolution.any_instance.stub(:save).and_return(false) - post :create, {solution: { "number" => "invalid value" }}, valid_session + post :create, params: { solution: { "number" => "invalid value" } }, session: valid_session expect(assigns(:solution)).to be_a_new(CommunitySolution) end it "re-renders the 'new' template" do # Trigger the behavior that occurs when invalid params are submitted CommunitySolution.any_instance.stub(:save).and_return(false) - post :create, {solution: { "number" => "invalid value" }}, valid_session + post :create, params: { solution: { "number" => "invalid value" } }, session: valid_session expect(response).to render_template("new") end end @@ -70,18 +70,18 @@ module Api::V1 # receives the :update_attributes message with whatever params are # submitted in the request. expect(CommunitySolution.any_instance).to_receive(:update_attributes).with({ "number" => "1" }) - put :update, {id: solution.to_param, solution: { "number" => "1" }}, valid_session + put :update, params: { id: solution.to_param, solution: { "number" => "1" } }, session: valid_session end it "assigns the requested solution as @solution" do solution = CommunitySolution.create! valid_attributes - put :update, {id: solution.to_param, solution: valid_attributes}, valid_session + put :update, params: { id: solution.to_param, solution: valid_attributes }, session: valid_session expect(assigns(:solution)).to eq(solution) end it "redirects to the solution" do solution = CommunitySolution.create! valid_attributes - put :update, {id: solution.to_param, solution: valid_attributes}, valid_session + put :update, params: { id: solution.to_param, solution: valid_attributes }, session: valid_session expect(response).to redirect_to(solution) end end @@ -91,7 +91,7 @@ module Api::V1 solution = CommunitySolution.create! valid_attributes # Trigger the behavior that occurs when invalid params are submitted CommunitySolution.any_instance.stub(:save).and_return(false) - put :update, {id: solution.to_param, solution: { "number" => "invalid value" }}, valid_session + put :update, params: { id: solution.to_param, solution: { "number" => "invalid value" } }, session: valid_session expect(assigns(:solution)).to eq(solution) end @@ -99,7 +99,7 @@ module Api::V1 solution = CommunitySolution.create! valid_attributes # Trigger the behavior that occurs when invalid params are submitted CommunitySolution.any_instance.stub(:save).and_return(false) - put :update, {id: solution.to_param, solution: { "number" => "invalid value" }}, valid_session + put :update, params: { id: solution.to_param, solution: { "number" => "invalid value" } }, session: valid_session expect(response).to render_template("edit") end end @@ -109,13 +109,13 @@ module Api::V1 it "destroys the requested solution" do solution = CommunitySolution.create! valid_attributes expect { - delete :destroy, {id: solution.to_param}, valid_session + delete :destroy, params: { id: solution.to_param }, session: valid_session }.to change(CommunitySolution, :count).by(-1) end it "redirects to the solutions list" do solution = CommunitySolution.create! valid_attributes - delete :destroy, {id: solution.to_param}, valid_session + delete :destroy, params: { id: solution.to_param }, session: valid_session expect(response).to redirect_to(solutions_url) end end diff --git a/spec/controllers/api/v1/deputizations_controller_spec.rb b/spec/controllers/api/v1/deputizations_controller_spec.rb index a1d0e964..176e434d 100644 --- a/spec/controllers/api/v1/deputizations_controller_spec.rb +++ b/spec/controllers/api/v1/deputizations_controller_spec.rb @@ -11,7 +11,7 @@ module Api::V1 context "GET index" do it "assigns all deputizations as @deputizations" do deputization = Deputization.create! valid_attributes - get :index, {}, valid_session + get :index, session: valid_session expect(assigns(:deputizations)).to eq([deputization]) end end @@ -20,18 +20,18 @@ module Api::V1 context "with valid params" do it "creates a new Deputization" do expect { - post :create, {:deputization => valid_attributes}, valid_session + post :create, params: { :deputization => valid_attributes }, session: valid_session }.to change(Deputization, :count).by(1) end it "assigns a newly created deputization as @deputization" do - post :create, {:deputization => valid_attributes}, valid_session + post :create, params: { :deputization => valid_attributes }, session: valid_session expect(assigns(:deputization)).to be_a(Deputization) expect(assigns(:deputization)).to be_persisted end it "redirects to the created deputization" do - post :create, {:deputization => valid_attributes}, valid_session + post :create, params: { :deputization => valid_attributes }, session: valid_session expect(response).to redirect_to(Deputization.last) end end @@ -40,14 +40,14 @@ module Api::V1 it "assigns a newly created but unsaved deputization as @deputization" do # Trigger the behavior that occurs when invalid params are submitted Deputization.any_instance.stub(:save).and_return(false) - post :create, {:deputization => { "number" => "invalid value" }}, valid_session + post :create, params: { :deputization => { "number" => "invalid value" } }, session: valid_session expect(assigns(:deputization)).to be_a_new(Deputization) end it "re-renders the 'new' template" do # Trigger the behavior that occurs when invalid params are submitted Deputization.any_instance.stub(:save).and_return(false) - post :create, {:deputization => { "number" => "invalid value" }}, valid_session + post :create, params: { :deputization => { "number" => "invalid value" } }, session: valid_session expect(response).to render_template("new") end end @@ -57,13 +57,13 @@ module Api::V1 it "destroys the requested deputization" do deputization = Deputization.create! valid_attributes expect { - delete :destroy, {id: deputization.to_param}, valid_session + delete :destroy, params: { id: deputization.to_param }, session: valid_session }.to change(Deputization, :count).by(-1) end it "redirects to the deputizations list" do deputization = Deputization.create! valid_attributes - delete :destroy, {id: deputization.to_param}, valid_session + delete :destroy, params: { id: deputization.to_param }, session: valid_session expect(response).to redirect_to(deputizations_url) end end diff --git a/spec/controllers/api/v1/exercises_controller_spec.rb b/spec/controllers/api/v1/exercises_controller_spec.rb index afe7f693..cb7c241b 100644 --- a/spec/controllers/api/v1/exercises_controller_spec.rb +++ b/spec/controllers/api/v1/exercises_controller_spec.rb @@ -7,6 +7,7 @@ module Api::V1 application = FactoryBot.create :doorkeeper_application @user = FactoryBot.create :user, :agreed_to_terms + @user_1 = FactoryBot.create :user, :agreed_to_terms admin = FactoryBot.create :user, :administrator, :agreed_to_terms @application_token = FactoryBot.create :doorkeeper_access_token, application: application, @@ -19,9 +20,12 @@ module Api::V1 resource_owner_id: admin.id @exercise = FactoryBot.build(:exercise) - @exercise.publication.authors << FactoryBot.build( + @exercise.publication.authors << FactoryBot.create( :author, user: @user, publication: @exercise.publication ) + @exercise.publication.copyright_holders << FactoryBot.create( + :copyright_holder, user: @user, publication: @exercise.publication + ) @exercise.nickname = 'MyExercise' @exercise.save! end @@ -34,16 +38,21 @@ module Api::V1 10.times { FactoryBot.create(:exercise, :published) } - tested_strings = ["%adipisci%", "%draft%"] - Exercise.joins {questions.outer.stems.outer} - .joins {questions.outer.answers.outer} - .where do - title.like_any(tested_strings) |\ - stimulus.like_any(tested_strings) |\ - questions.stimulus.like_any(tested_strings) |\ - stems.content.like_any(tested_strings) |\ - answers.content.like_any(tested_strings) - end.delete_all + ex = Exercise.arel_table + qu = Question.arel_table + st = Stem.arel_table + ans = Answer.arel_table + + tested_strings = [ "%adipisci%", "%draft%" ] + + ex_ids = Exercise.left_joins(questions: [:stems, :answers]).where( + ex[:title].matches_any(tested_strings) + .or(ex[:stimulus].matches_any(tested_strings)) + .or(qu[:stimulus].matches_any(tested_strings)) + .or(st[:content].matches_any(tested_strings)) + .or(ans[:content].matches_any(tested_strings))).pluck(:id) + + Exercise.where(id: ex_ids).delete_all @exercise_1 = FactoryBot.build(:exercise, :published) Api::V1::Exercises::Representer.new(@exercise_1).from_hash( @@ -59,6 +68,12 @@ module Api::V1 'formats' => [ 'multiple-choice', 'free-response' ] }] ) + @exercise_1.publication.authors << FactoryBot.create( + :author, user: @user_1, publication: @exercise_1.publication + ) + @exercise_1.publication.copyright_holders << FactoryBot.create( + :copyright_holder, user: @user_1, publication: @exercise_1.publication + ) @exercise_1.save! @exercise_2 = FactoryBot.build(:exercise, :published) @@ -75,6 +90,12 @@ module Api::V1 'formats' => [ 'multiple-choice', 'free-response' ] }] ) + @exercise_2.publication.authors << FactoryBot.create( + :author, user: @user_1, publication: @exercise_2.publication + ) + @exercise_2.publication.copyright_holders << FactoryBot.create( + :copyright_holder, user: @user_1, publication: @exercise_2.publication + ) @exercise_2.save! @exercise_draft = FactoryBot.build(:exercise) @@ -99,7 +120,7 @@ module Api::V1 context "no matches" do it "does not return drafts that the user is not allowed to see" do - send method, :index, q: 'content:draft', format: :json + send method, :index, params: {q: 'content:draft', format: :json} expect(response).to have_http_status(:success) expected_response = { @@ -114,9 +135,10 @@ module Api::V1 context "single match" do it "returns drafts that the user is allowed to see" do @exercise_draft.publication.authors << Author.new(user: @user) + @exercise_draft.publication.copyright_holders << CopyrightHolder.new(user: @user) @exercise_draft.reload @user.reload - send method, :index, q: 'content:draft', format: :json + send method, :index, params: {q: 'content:draft', format: :json} expect(response).to have_http_status(:success) expected_response = { @@ -128,7 +150,7 @@ module Api::V1 end it "returns an Exercise matching the content" do - send method, :index, q: 'content:"aDiPiScInG eLiT"', format: :json + send method, :index, params: {q: 'content:"aDiPiScInG eLiT"', format: :json } expect(response).to have_http_status(:success) expected_response = { @@ -140,7 +162,7 @@ module Api::V1 end it "returns an Exercise matching the tags" do - send method, :index, q: 'tag:tAg1', format: :json + send method, :index, params: {q: 'tag:tAg1', format: :json } expect(response).to have_http_status(:success) expected_response = { @@ -154,7 +176,7 @@ module Api::V1 context "multiple matches" do it "returns Exercises matching the content" do - send method, :index, q: 'content:AdIpIsCi', format: :json + send method, :index, params: {q: 'content:AdIpIsCi', format: :json } expect(response).to have_http_status(:success) expected_response = { @@ -167,7 +189,7 @@ module Api::V1 end it "returns Exercises matching the tags" do - send method, :index, q: 'tag:TaG2', format: :json + send method, :index, params: {q: 'tag:TaG2', format: :json } expect(response).to have_http_status(:success) expected_response = { @@ -180,8 +202,8 @@ module Api::V1 end it "sorts by multiple fields in different directions" do - send method, :index, q: 'content:aDiPiScI', order_by: "number DESC, version ASC", - format: :json + send method, :index, params: {q: 'content:aDiPiScI', order_by: "number DESC, version ASC", + format: :json } expect(response).to have_http_status(:success) expected_response = { @@ -214,7 +236,7 @@ module Api::V1 end it "returns the Exercise requested by group_uuid and version" do - api_get :show, @user_token, parameters: { + api_get :show, @user_token, params: { id: "#{@exercise.group_uuid}@#{@exercise.version}" } expect(response).to have_http_status(:success) @@ -225,7 +247,7 @@ module Api::V1 end it "returns the Exercise requested by uuid" do - api_get :show, @user_token, parameters: { id: @exercise.uuid } + api_get :show, @user_token, params: { id: @exercise.uuid } expect(response).to have_http_status(:success) expect(response.body_as_hash).to match(a_hash_including(uuid: @exercise.uuid)) expect(response.body_as_hash[:versions]).to( @@ -234,7 +256,7 @@ module Api::V1 end it "returns the Exercise requested by uid" do - api_get :show, @user_token, parameters: { id: @exercise.uid } + api_get :show, @user_token, params: { id: @exercise.uid } expect(response).to have_http_status(:success) expect(response.body_as_hash).to match(a_hash_including(uuid: @exercise.uuid)) expect(response.body_as_hash[:versions]).to( @@ -243,7 +265,7 @@ module Api::V1 end it "returns the latest published Exercise if only the group_uuid is specified" do - api_get :show, @user_token, parameters: { id: @exercise.group_uuid } + api_get :show, @user_token, params: { id: @exercise.group_uuid } expect(response).to have_http_status(:success) expect(response.body_as_hash).to match(a_hash_including(uuid: @exercise.uuid)) expect(response.body_as_hash[:versions]).to( @@ -252,7 +274,7 @@ module Api::V1 end it "returns the latest published Exercise if only the number is specified" do - api_get :show, @user_token, parameters: { id: @exercise.number } + api_get :show, @user_token, params: { id: @exercise.number } expect(response).to have_http_status(:success) expect(response.body_as_hash).to match(a_hash_including(uuid: @exercise.uuid)) expect(response.body_as_hash[:versions]).to( @@ -261,7 +283,7 @@ module Api::V1 end it "returns the latest draft Exercise if \"group_uuid@draft\" is requested" do - api_get :show, @user_token, parameters: { id: "#{@exercise.group_uuid}@draft" } + api_get :show, @user_token, params: { id: "#{@exercise.group_uuid}@draft" } expect(response).to have_http_status(:success) expect(response.body_as_hash).to match(a_hash_including(uuid: @exercise_2.uuid)) expect(response.body_as_hash[:versions]).to( @@ -270,7 +292,7 @@ module Api::V1 end it "returns the latest draft Exercise if \"number@draft\" is requested" do - api_get :show, @user_token, parameters: { id: "#{@exercise.number}@draft" } + api_get :show, @user_token, params: { id: "#{@exercise.number}@draft" } expect(response).to have_http_status(:success) expect(response.body_as_hash).to match(a_hash_including(uuid: @exercise_2.uuid)) expect(response.body_as_hash[:versions]).to( @@ -280,7 +302,7 @@ module Api::V1 it "returns the latest version of a Exercise if \"@latest\" is requested" do @exercise_1.publication.update_attributes(version: 1000) - api_get :show, @user_token, parameters: { id: "#{@exercise.number}@latest" } + api_get :show, @user_token, params: { id: "#{@exercise.number}@latest" } expect(response).to have_http_status(:success) expect(response.body_as_hash).to match(a_hash_including(uuid: @exercise_1.uuid)) expect(response.body_as_hash[:versions]).to( @@ -293,7 +315,7 @@ module Api::V1 @exercise_2.destroy expect do - api_get :show, @user_token, parameters: { id: "#{@exercise.number}@draft" } + api_get :show, @user_token, params: { id: "#{@exercise.number}@draft" } end.to change{ Exercise.count }.by(1) expect(response).to have_http_status(:success) @@ -317,7 +339,7 @@ module Api::V1 after(:all) { DatabaseCleaner.clean } it "shows solutions for published exercises if the requestor is an app" do - api_get :show, @application_token, parameters: { id: @exercise.uid } + api_get :show, @application_token, params: { id: @exercise.uid } expect(response).to have_http_status(:success) expect(response.body_as_hash[:questions].first[:collaborator_solutions]).not_to be_empty @@ -328,7 +350,7 @@ module Api::V1 end it "shows solutions for published exercises if the requestor is allowed to edit it" do - api_get :show, @user_token, parameters: { id: @exercise.uid } + api_get :show, @user_token, params: { id: @exercise.uid } expect(response).to have_http_status(:success) expect(response.body_as_hash[:questions].first[:collaborator_solutions]).not_to be_empty @@ -340,8 +362,15 @@ module Api::V1 it "hides solutions for published exercises if the requestor is not allowed to edit it" do @exercise.publication.authors.destroy_all + @exercise.publication.copyright_holders.destroy_all + @exercise.publication.authors << FactoryBot.create( + :author, user: @user_1, publication: @exercise.publication + ) + @exercise.publication.copyright_holders << FactoryBot.create( + :copyright_holder, user: @user_1, publication: @exercise.publication + ) - api_get :show, @user_token, parameters: { id: @exercise.uid } + api_get :show, @user_token, params: { id: @exercise.uid } expect(response).to have_http_status(:success) expect(response.body_as_hash[:questions].first['collaborator_solutions']).to be_nil @@ -352,7 +381,7 @@ module Api::V1 end it "includes versions of the exercise" do - api_get :show, @user_token, parameters: { id: @exercise.uid } + api_get :show, @user_token, params: { id: @exercise.uid } expect(response).to have_http_status(:success) expect(response.body_as_hash[:versions]).to( eq([@exercise_2.version, @exercise_1.version, @exercise.version]) @@ -375,7 +404,7 @@ module Api::V1 it "creates the requested Exercise and assigns the user as author and CR holder" do expect do - api_post :create, @user_token, raw_post_data: Api::V1::Exercises::Representer.new( + api_post :create, @user_token, body: Api::V1::Exercises::Representer.new( @exercise ).to_hash(user_options: { user: @user }) end.to change { Exercise.count }.by(1) @@ -410,9 +439,12 @@ module Api::V1 exercise.publication.authors << FactoryBot.build( :author, user: @user, publication: @exercise.publication ) + exercise.publication.copyright_holders << FactoryBot.build( + :copyright_holder, user: @user, publication: @exercise.publication + ) expect do - api_post :create, @user_token, raw_post_data: Api::V1::Exercises::Representer.new( + api_post :create, @user_token, body: Api::V1::Exercises::Representer.new( exercise ).to_hash(user_options: { user: @user }) end.to change { Exercise.count }.by(1) @@ -427,7 +459,7 @@ module Api::V1 FactoryBot.create :publication_group, nickname: 'MyExercise' expect do - api_post :create, @user_token, raw_post_data: Api::V1::Exercises::Representer.new( + api_post :create, @user_token, body: Api::V1::Exercises::Representer.new( @exercise ).to_hash(user_options: { user: @user }) end.not_to change { Exercise.count } @@ -442,7 +474,7 @@ module Api::V1 before { @old_attributes = @exercise.reload.attributes } it "updates the requested Exercise" do - api_patch :update, @user_token, parameters: { id: @exercise.uid }, raw_post_data: { + api_patch :update, @user_token, params: { id: @exercise.uid }, body: { nickname: 'MyExercise', title: "Ipsum lorem" } expect(response).to have_http_status(:success) @@ -459,7 +491,7 @@ module Api::V1 @exercise.publication.publish.save! expect do - api_patch :update, @user_token, parameters: { id: @exercise.uid }, raw_post_data: { + api_patch :update, @user_token, params: { id: @exercise.uid }, body: { nickname: 'MyExercise', title: "Ipsum lorem" } end.to raise_error(SecurityTransgression) @@ -471,7 +503,7 @@ module Api::V1 it "fails if the nickname has already been taken" do FactoryBot.create :publication_group, nickname: 'MyExercise2' - api_patch :update, @user_token, parameters: { id: @exercise.uid }, raw_post_data: { + api_patch :update, @user_token, params: { id: @exercise.uid }, body: { nickname: 'MyExercise2', title: "Ipsum lorem" } @@ -489,7 +521,7 @@ module Api::V1 exercise_2.reload id = "#{@exercise.number}@draft" - api_patch :update, @user_token, parameters: { id: id }, raw_post_data: { + api_patch :update, @user_token, params: { id: id }, body: { nickname: 'MyExercise', title: "Ipsum lorem" } expect(response).to have_http_status(:success) @@ -512,7 +544,7 @@ module Api::V1 id = "#{@exercise.number}@draft" expect do - api_patch :update, @user_token, parameters: { id: id }, raw_post_data: { + api_patch :update, @user_token, params: { id: id }, body: { nickname: 'MyExercise', title: "Ipsum lorem" } end.to change{ Exercise.count }.by(1) @@ -538,7 +570,7 @@ module Api::V1 context "DELETE destroy" do it "deletes the requested draft Exercise" do expect do - api_delete :destroy, @user_token, parameters: { id: @exercise.uid } + api_delete :destroy, @user_token, params: { id: @exercise.uid } end.to change(Exercise, :count).by(-1) expect(response).to have_http_status(:success) expect(Exercise.where(id: @exercise.id)).not_to exist diff --git a/spec/controllers/api/v1/publications_controller_spec.rb b/spec/controllers/api/v1/publications_controller_spec.rb index 11a38744..cffd9950 100644 --- a/spec/controllers/api/v1/publications_controller_spec.rb +++ b/spec/controllers/api/v1/publications_controller_spec.rb @@ -7,16 +7,26 @@ module Api::V1 let(:vocab_term) { FactoryBot.create :vocab_term } let(:solution) { FactoryBot.create :community_solution } - let(:exercise_author) { + let!(:exercise_author) { FactoryBot.create :author, publication: exercise.publication } - let(:vocab_term_author) { + let!(:vocab_term_author) { FactoryBot.create :author, publication: vocab_term.publication } - let(:solution_author) { + let!(:solution_author) { FactoryBot.create :author, publication: solution.publication } + let!(:exercise_copyright_holder) { + FactoryBot.create :copyright_holder, publication: exercise.publication + } + let!(:vocab_term_copyright_holder) { + FactoryBot.create :copyright_holder, publication: vocab_term.publication + } + let!(:solution_copyright_holder) { + FactoryBot.create :copyright_holder, publication: solution.publication + } + let(:exercise_author_token) { FactoryBot.create :doorkeeper_access_token, resource_owner_id: exercise_author.user_id @@ -36,7 +46,7 @@ module Api::V1 expect(exercise.reload.is_published?).to eq false api_put :publish, exercise_author_token, - parameters: { exercise_id: exercise.uid.to_s } + params: { exercise_id: exercise.uid.to_s } expected_response = Api::V1::Exercises::Representer .new(exercise.reload) @@ -54,7 +64,7 @@ module Api::V1 end api_put :publish, exercise_author_token, - parameters: { exercise_id: exercise.uid.to_s } + params: { exercise_id: exercise.uid.to_s } expected_response = { errors: [{ code: 'exercise_has_a_question_with_only_incorrect_answers', @@ -72,7 +82,7 @@ module Api::V1 expect(vocab_term.reload.is_published?).to eq false api_put :publish, vocab_term_author_token, - parameters: { vocab_term_id: vocab_term.uid.to_s } + params: { vocab_term_id: vocab_term.uid.to_s } expected_response = \ Api::V1::Vocabs::TermWithDistractorsAndExerciseIdsRepresenter.new(vocab_term.reload) @@ -88,7 +98,7 @@ module Api::V1 vocab_term.vocab_distractors.delete_all api_put :publish, vocab_term_author_token, - parameters: { vocab_term_id: vocab_term.uid.to_s } + params: { vocab_term_id: vocab_term.uid.to_s } expected_response = { errors: [{ code: 'vocab_term_must_have_at_least_1_distractor', @@ -105,7 +115,7 @@ module Api::V1 it "publishes the requested community solution" do expect(solution.reload.is_published?).to eq false - api_put :publish, solution_author_token, parameters: { + api_put :publish, solution_author_token, params: { community_solution_id: solution.uid.to_s } @@ -124,7 +134,7 @@ module Api::V1 expect{ api_put :publish, exercise_author_token, - parameters: { exercise_id: exercise.uid.to_s, + params: { exercise_id: exercise.uid.to_s, vocab_term_id: vocab_term.uid.to_s, community_solution_id: solution.uid.to_s } }.to raise_error(ActionController::BadRequest) diff --git a/spec/controllers/api/v1/users_controller_spec.rb b/spec/controllers/api/v1/users_controller_spec.rb index e46fd998..7b04dbca 100644 --- a/spec/controllers/api/v1/users_controller_spec.rb +++ b/spec/controllers/api/v1/users_controller_spec.rb @@ -28,9 +28,10 @@ module Api::V1 before do 100.times { FactoryBot.create(:user) } - User.joins(:account).where {(account.first_name.like '%doe%') | - (account.last_name.like '%doe%') | - (account.username.like '%doe%')}.delete_all + acc = OpenStax::Accounts::Account.arel_table + User.joins(:account).where(acc[:first_name].matches('%doe%').or( + acc[:last_name].matches('%doe%')).or( + acc[:username].matches('%doe%'))).delete_all @john_doe = FactoryBot.create :user, first_name: "John", last_name: "Doe", @@ -43,7 +44,7 @@ module Api::V1 end it "returns no results if the maximum number of results is exceeded" do - api_get :index, admin_token, parameters: {q: ''} + api_get :index, admin_token, params: {q: ''} expect(response).to have_http_status(:success) expected_response = { @@ -55,7 +56,7 @@ module Api::V1 end it "returns single results" do - api_get :index, application_token, parameters: { q: 'first_name:jOhN last_name:dOe' } + api_get :index, application_token, params: { q: 'first_name:jOhN last_name:dOe' } expect(response).to have_http_status(:success) expected_response = { @@ -72,7 +73,8 @@ module Api::V1 self_reported_role: @john_doe.role, uuid: @john_doe.uuid, support_identifier: @john_doe.support_identifier, - is_test: true + is_test: true, + school_type: 'unknown_school_type' } ] } @@ -81,7 +83,7 @@ module Api::V1 end it "returns multiple results" do - api_get :index, user_token, parameters: {q: 'last_name:DoE'} + api_get :index, user_token, params: {q: 'last_name:DoE'} expect(response).to have_http_status(:success) expected_response = { @@ -98,7 +100,8 @@ module Api::V1 self_reported_role: @jane_doe.role, uuid: @jane_doe.uuid, support_identifier: @jane_doe.support_identifier, - is_test: true + is_test: true, + school_type: 'unknown_school_type' }, { id: @john_doe.account.openstax_uid, @@ -111,7 +114,9 @@ module Api::V1 self_reported_role: @john_doe.role, uuid: @john_doe.uuid, support_identifier: @john_doe.support_identifier, - is_test: true + is_test: true, + school_type: 'unknown_school_type' + } ] } @@ -120,7 +125,7 @@ module Api::V1 end it "sorts by multiple fields in different directions" do - api_get :index, user_token, parameters: {q: 'username:doe', + api_get :index, user_token, params: {q: 'username:doe', order_by: "first_name DESC, last_name"} expect(response).to have_http_status(:success) @@ -138,7 +143,9 @@ module Api::V1 self_reported_role: @john_doe.role, uuid: @john_doe.uuid, support_identifier: @john_doe.support_identifier, - is_test: true + is_test: true, + school_type: 'unknown_school_type' + }, { id: @jane_doe.account.openstax_uid, @@ -151,7 +158,9 @@ module Api::V1 self_reported_role: @jane_doe.role, uuid: @jane_doe.uuid, support_identifier: @jane_doe.support_identifier, - is_test: true + is_test: true, + school_type: 'unknown_school_type' + } ] } @@ -184,7 +193,7 @@ module Api::V1 end it "ignores id parameters" do - api_get :show, user_token, parameters: {id: admin.id, user_id: admin.id} + api_get :show, user_token, params: {id: admin.id, user_id: admin.id} expect(response).to have_http_status(:success) expected_response = { @@ -208,7 +217,7 @@ module Api::V1 context "PATCH update" do it "updates the current User's profile" do - api_patch :update, user_token, raw_post_data: { + api_patch :update, user_token, body: { first_name: "Jerry", last_name: "Mouse" } expect(response).to have_http_status(:success) @@ -218,9 +227,9 @@ module Api::V1 end it "ignores id parameters" do - api_patch :update, user_token, raw_post_data: { + api_patch :update, user_token, body: { first_name: "Jerry", last_name: "Mouse" - }, parameters: {id: admin.id, user_id: admin.id} + }, params: {id: admin.id, user_id: admin.id} expect(response).to have_http_status(:success) user.reload admin.reload @@ -242,7 +251,7 @@ module Api::V1 end it "ignores id parameters" do - api_delete :destroy, user_token, parameters: {id: admin.id, user_id: admin.id} + api_delete :destroy, user_token, params: {id: admin.id, user_id: admin.id} expect(response).to have_http_status(:success) user.reload admin.reload diff --git a/spec/controllers/api/v1/vocab_terms_controller_spec.rb b/spec/controllers/api/v1/vocab_terms_controller_spec.rb index b3582b9e..1336ef4e 100644 --- a/spec/controllers/api/v1/vocab_terms_controller_spec.rb +++ b/spec/controllers/api/v1/vocab_terms_controller_spec.rb @@ -7,6 +7,9 @@ module Api::V1 application = FactoryBot.create :doorkeeper_application @user = FactoryBot.create :user, :agreed_to_terms + @user_1 = FactoryBot.create :user, :agreed_to_terms + @user_2 = FactoryBot.create :user, :agreed_to_terms + @user_draft = FactoryBot.create :user, :agreed_to_terms admin = FactoryBot.create :user, :administrator, :agreed_to_terms @application_token = FactoryBot.create :doorkeeper_access_token, application: application, @@ -22,6 +25,9 @@ module Api::V1 @vocab_term.publication.authors << FactoryBot.build( :author, user: @user, publication: @vocab_term.publication ) + @vocab_term.publication.copyright_holders << FactoryBot.build( + :copyright_holder, user: @user, publication: @vocab_term.publication + ) @vocab_term.nickname = 'MyVocab' @vocab_term.save! end @@ -35,11 +41,12 @@ module Api::V1 10.times do vt = FactoryBot.create(:vocab_term, :published) vt.publication.authors << Author.new(publication: vt.publication, user: @user) + vt.publication.copyright_holders << CopyrightHolder.new(publication: vt.publication, user: @user) end tested_strings = ["%lorem ipsu%", "%adipiscing elit%", "draft"] - VocabTerm.where {(name.like_any tested_strings) | - (definition.like_any tested_strings)}.delete_all + VocabTerm.where(VocabTerm.arel_table[:name].matches_any(tested_strings).or( + VocabTerm.arel_table[:definition].matches_any(tested_strings))).delete_all @vocab_term_1 = FactoryBot.build(:vocab_term, :published) Api::V1::Vocabs::TermWithDistractorsAndExerciseIdsRepresenter.new( @@ -50,6 +57,8 @@ module Api::V1 'definition' => "Dolor sit amet", 'distractor_literals' => ["Consectetur adipiscing elit", "Sed do eiusmod tempor"] ) + @vocab_term_1.publication.authors << Author.new(publication: @vocab_term_1.publication, user: @user_1) + @vocab_term_1.publication.copyright_holders << CopyrightHolder.new(publication: @vocab_term_1.publication, user: @user_1) @vocab_term_1.save! @vocab_term_2 = FactoryBot.build(:vocab_term, :published) @@ -61,6 +70,8 @@ module Api::V1 'definition' => "Quia dolor sit amet", 'distractor_literals' => ["Consectetur adipisci velit", "Sed quia non numquam"] ) + @vocab_term_2.publication.authors << Author.new(publication: @vocab_term_2.publication, user: @user_2) + @vocab_term_2.publication.copyright_holders << CopyrightHolder.new(publication: @vocab_term_2.publication, user: @user_2) @vocab_term_2.save! @vocab_term_draft = FactoryBot.build(:vocab_term) @@ -72,6 +83,8 @@ module Api::V1 'definition' => "Not ready for prime time", 'distractor_literals' => ["Release to production NOW"] ) + @vocab_term_draft.publication.authors << Author.new(publication: @vocab_term_draft.publication, user: @user_draft) + @vocab_term_draft.publication.copyright_holders << CopyrightHolder.new(publication: @vocab_term_draft.publication, user: @user_draft) @vocab_term_draft.save! end after(:all) { DatabaseCleaner.clean } @@ -80,7 +93,7 @@ module Api::V1 context "no matches" do it "does not return drafts that the user is not allowed to see" do - send method, :index, q: 'content:draft', format: :json + send method, :index, params: { q: 'content:draft', format: :json } expect(response).to have_http_status(:success) expected_response = { @@ -95,9 +108,10 @@ module Api::V1 context "single match" do it "returns drafts that the user is allowed to see" do @vocab_term_draft.publication.authors << Author.new(user: @user) + @vocab_term_draft.publication.copyright_holders << CopyrightHolder.new(user: @user) @vocab_term_draft.reload @user.reload - send method, :index, q: 'content:draft', format: :json + send method, :index, params: { q: 'content:draft', format: :json } expect(response).to have_http_status(:success) expected_response = { @@ -109,7 +123,7 @@ module Api::V1 end it "returns a VocabTerm matching the content" do - send method, :index, q: 'content:"oLoReM iPsU"', format: :json + send method, :index, params: { q: 'content:"oLoReM iPsU"', format: :json } expect(response).to have_http_status(:success) expected_response = { @@ -121,7 +135,7 @@ module Api::V1 end it "returns a VocabTerm matching the tags" do - send method, :index, q: 'tag:tAg1', format: :json + send method, :index, params: { q: 'tag:tAg1', format: :json } expect(response).to have_http_status(:success) expected_response = { @@ -135,7 +149,7 @@ module Api::V1 context "multiple matches" do it "returns VocabTerms matching the content" do - send method, :index, q: 'content:"lOrEm IpSuM"', format: :json + send method, :index, params: { q: 'content:"lOrEm IpSuM"', format: :json } expect(response).to have_http_status(:success) expected_response = { @@ -148,7 +162,7 @@ module Api::V1 end it "returns VocabTerms matching the tags" do - send method, :index, q: 'tag:TaG2', format: :json + send method, :index, params: { q: 'tag:TaG2', format: :json } expect(response).to have_http_status(:success) expected_response = { @@ -161,8 +175,8 @@ module Api::V1 end it "sorts by multiple fields in different directions" do - send method, :index, q: 'content:"lOrEm IpSuM"', order_by: "number DESC, version ASC", - format: :json + send method, :index, params: {q: 'content:"lOrEm IpSuM"', order_by: "number DESC, version ASC", + format: :json } expect(response).to have_http_status(:success) expected_response = { @@ -189,7 +203,7 @@ module Api::V1 after(:all) { DatabaseCleaner.clean } it "returns the VocabTerm requested by group_uuid and version" do - api_get :show, @user_token, parameters: { + api_get :show, @user_token, params: { id: "#{@vocab_term.group_uuid}@#{@vocab_term.version}" } expect(response).to have_http_status(:success) @@ -197,37 +211,37 @@ module Api::V1 end it "returns the VocabTerm requested by uuid" do - api_get :show, @user_token, parameters: { id: @vocab_term.uuid } + api_get :show, @user_token, params: { id: @vocab_term.uuid } expect(response).to have_http_status(:success) expect(response.body_as_hash).to match(a_hash_including(uuid: @vocab_term.uuid)) end it "returns the VocabTerm requested by uid" do - api_get :show, @user_token, parameters: { id: @vocab_term.uid } + api_get :show, @user_token, params: { id: @vocab_term.uid } expect(response).to have_http_status(:success) expect(response.body_as_hash).to match(a_hash_including(uuid: @vocab_term.uuid)) end it "returns the latest published VocabTerm if only the group_uuid is specified" do - api_get :show, @user_token, parameters: { id: @vocab_term.group_uuid } + api_get :show, @user_token, params: { id: @vocab_term.group_uuid } expect(response).to have_http_status(:success) expect(response.body_as_hash).to match(a_hash_including(uuid: @vocab_term.uuid)) end it "returns the latest published VocabTerm if only the number is specified" do - api_get :show, @user_token, parameters: { id: @vocab_term.number } + api_get :show, @user_token, params: { id: @vocab_term.number } expect(response).to have_http_status(:success) expect(response.body_as_hash).to match(a_hash_including(uuid: @vocab_term.uuid)) end it "returns the latest draft VocabTerm if \"group_uuid@draft\" is requested" do - api_get :show, @user_token, parameters: { id: "#{@vocab_term.group_uuid}@draft" } + api_get :show, @user_token, params: { id: "#{@vocab_term.group_uuid}@draft" } expect(response).to have_http_status(:success) expect(response.body_as_hash).to match(a_hash_including(uuid: @vocab_term_2.uuid)) end it "returns the latest draft VocabTerm if \"number@draft\" is requested" do - api_get :show, @user_token, parameters: { id: "#{@vocab_term.number}@draft" } + api_get :show, @user_token, params: { id: "#{@vocab_term.number}@draft" } expect(response).to have_http_status(:success) expect(response.body_as_hash).to match(a_hash_including(uuid: @vocab_term_2.uuid)) end @@ -236,7 +250,7 @@ module Api::V1 @vocab_term_2.destroy expect do - api_get :show, @user_token, parameters: { id: "#{@vocab_term.number}@draft" } + api_get :show, @user_token, params: { id: "#{@vocab_term.number}@draft" } end.to change{ VocabTerm.count }.by(1) expect(response).to have_http_status(:success) @@ -265,7 +279,7 @@ module Api::V1 it "creates the requested VocabTerm and assigns the user as author and CR holder" do expect do api_post :create, @user_token, - raw_post_data: Api::V1::Vocabs::TermWithDistractorsAndExerciseIdsRepresenter.new( + body: Api::V1::Vocabs::TermWithDistractorsAndExerciseIdsRepresenter.new( @vocab_term ).to_hash(user_options: { user: @user }) end.to change { VocabTerm.count }.by(1) @@ -285,7 +299,7 @@ module Api::V1 expect do api_post :create, @user_token, - raw_post_data: Api::V1::Vocabs::TermWithDistractorsAndExerciseIdsRepresenter.new( + body: Api::V1::Vocabs::TermWithDistractorsAndExerciseIdsRepresenter.new( @vocab_term ).to_hash(user_options: { user: @user }) end.not_to change { VocabTerm.count } @@ -299,8 +313,8 @@ module Api::V1 before { @old_attributes = @vocab_term.reload.attributes } it "updates the requested VocabTerm" do - api_patch :update, @user_token, parameters: { id: @vocab_term.uid }, - raw_post_data: { nickname: 'MyVocab', term: "Ipsum lorem" } + api_patch :update, @user_token, params: { id: @vocab_term.uid }, + body: { nickname: 'MyVocab', term: "Ipsum lorem" } expect(response).to have_http_status(:success) @vocab_term.reload new_attributes = @vocab_term.attributes @@ -315,7 +329,7 @@ module Api::V1 @vocab_term.publication.publish.save! expect do - api_patch :update, @user_token, parameters: { id: @vocab_term.uid }, raw_post_data: { + api_patch :update, @user_token, params: { id: @vocab_term.uid }, body: { nickname: 'MyVocab', term: "Ipsum lorem" } end.to raise_error(SecurityTransgression) @@ -329,7 +343,7 @@ module Api::V1 it "fails if the nickname has already been taken" do FactoryBot.create :publication_group, nickname: 'MyVocab2' - api_patch :update, @user_token, parameters: { id: @vocab_term.uid }, raw_post_data: { + api_patch :update, @user_token, params: { id: @vocab_term.uid }, body: { nickname: 'MyVocab2', title: "Ipsum lorem" } @@ -348,8 +362,8 @@ module Api::V1 vocab_term_2.save! vocab_term_2.reload - api_patch :update, @user_token, parameters: { id: "#{@vocab_term.number}@draft" }, - raw_post_data: { nickname: 'MyVocab', term: "Ipsum lorem" } + api_patch :update, @user_token, params: { id: "#{@vocab_term.number}@draft" }, + body: { nickname: 'MyVocab', term: "Ipsum lorem" } expect(response).to have_http_status(:success) @vocab_term.reload @@ -371,8 +385,8 @@ module Api::V1 @vocab_term.publication.publish.save! expect do - api_patch :update, @user_token, parameters: { id: "#{@vocab_term.number}@draft" }, - raw_post_data: { + api_patch :update, @user_token, params: { id: "#{@vocab_term.number}@draft" }, + body: { nickname: 'MyVocab', term: "Ipsum lorem" } end.to change{ VocabTerm.count }.by(1) @@ -400,7 +414,7 @@ module Api::V1 context "DELETE destroy" do it "deletes the requested draft VocabTerm" do expect do - api_delete :destroy, @user_token, parameters: { id: @vocab_term.uid } + api_delete :destroy, @user_token, params: { id: @vocab_term.uid } end.to change(VocabTerm, :count).by(-1) expect(response).to have_http_status(:success) expect(VocabTerm.where(id: @vocab_term.id)).not_to exist diff --git a/spec/controllers/oauth/applications_controller_spec.rb b/spec/controllers/oauth/applications_controller_spec.rb index 1f63244e..fd55c01d 100644 --- a/spec/controllers/oauth/applications_controller_spec.rb +++ b/spec/controllers/oauth/applications_controller_spec.rb @@ -34,7 +34,7 @@ module Oauth context "GET index" do it "assigns the user's applications as @applications" do - get :index, {}, valid_session + get :index, session: valid_session expect(response.code).to eq('200') expect(assigns :applications).to include(group_1_application_1) expect(assigns :applications).to include(group_1_application_2) @@ -43,7 +43,7 @@ module Oauth end it "assigns all applications as @applications for admins" do - get :index, {}, admin_session + get :index, session: admin_session expect(response.code).to eq('200') expect(assigns :applications).to include(group_1_application_1) expect(assigns :applications).to include(group_1_application_2) @@ -54,21 +54,21 @@ module Oauth context "GET show" do it "assigns the requested application as @application" do - get :show, {id: group_1_application_1.to_param}, valid_session + get :show, params: {id: group_1_application_1.to_param}, session: valid_session expect(assigns(:application)).to eq(group_1_application_1) end end context "GET new" do it "assigns a new application as @application" do - get :new, {}, admin_session + get :new, session: admin_session expect(assigns(:application)).to be_a_new(Doorkeeper::Application) end end context "GET edit" do it "assigns the requested application as @application" do - get :edit, {id: group_1_application_1.to_param}, valid_session + get :edit, params: {id: group_1_application_1.to_param}, session: valid_session expect(assigns(:application)).to eq(group_1_application_1) end end @@ -79,18 +79,18 @@ module Oauth it "creates a new Application" do expect { - post :create, {doorkeeper_application: valid_attributes}, admin_session + post :create, params: {doorkeeper_application: valid_attributes}, session: admin_session }.to change(Doorkeeper::Application, :count).by(1) end it "assigns a newly created application as @application" do - post :create, {doorkeeper_application: valid_attributes}, admin_session + post :create, params: {doorkeeper_application: valid_attributes}, session: admin_session expect(assigns(:application)).to be_a(Doorkeeper::Application) expect(assigns(:application)).to be_persisted end it "redirects to the created application" do - post :create, {doorkeeper_application: valid_attributes}, admin_session + post :create, params: {doorkeeper_application: valid_attributes}, session: admin_session expect(response).to redirect_to( oauth_application_url(Doorkeeper::Application.last) ) @@ -100,13 +100,13 @@ module Oauth context "with invalid params" do it "assigns a newly created but unsaved application as @application" do # Trigger the behavior that occurs when invalid params are submitted - post :create, {doorkeeper_application: { "redirect_uri" => "invalid" }}, admin_session + post :create, params: {doorkeeper_application: { "redirect_uri" => "invalid" }}, session: admin_session expect(assigns(:application)).to be_a_new(Doorkeeper::Application) end it "re-renders the 'new' template" do # Trigger the behavior that occurs when invalid params are submitted - post :create, {doorkeeper_application: { "redirect_uri" => "invalid" }}, admin_session + post :create, params: {doorkeeper_application: { "redirect_uri" => "invalid" }}, session: admin_session expect(response).to render_template("new") end end @@ -114,22 +114,23 @@ module Oauth context "PATCH update" do context "with valid params" do + dummy_params = ActionController::Parameters.new({ "name" => "Dummy" }).permit! it "updates the requested application" do expect_any_instance_of(Doorkeeper::Application) - .to receive(:update_attributes).with({ "name" => "Dummy" }) - patch :update, {id: group_1_application_1.to_param, - doorkeeper_application: { "name" => "Dummy" }}, valid_session + .to receive(:update_attributes).with(dummy_params) + patch :update, params: {id: group_1_application_1.to_param, + doorkeeper_application: dummy_params}, session: valid_session end it "assigns the requested application as @application" do - patch :update, {id: group_1_application_1.to_param, - doorkeeper_application: { "name" => "Dummy" }}, valid_session + patch :update, params: {id: group_1_application_1.to_param, + doorkeeper_application: dummy_params}, session: valid_session expect(assigns(:application)).to eq(group_1_application_1) end it "redirects to the application" do - patch :update, {id: group_1_application_1.to_param, - doorkeeper_application: { "name" => "Dummy" }}, valid_session + patch :update, params: {id: group_1_application_1.to_param, + doorkeeper_application: dummy_params}, session: valid_session expect(response).to redirect_to( oauth_application_url(group_1_application_1) ) @@ -139,15 +140,15 @@ module Oauth context "with invalid params" do it "assigns the application as @application" do # Trigger the behavior that occurs when invalid params are submitted - patch :update, {id: group_1_application_1.to_param, - doorkeeper_application: { "redirect_uri" => "invalid" }}, valid_session + patch :update, params: {id: group_1_application_1.to_param, + doorkeeper_application: { "redirect_uri" => "invalid" }}, session: valid_session expect(assigns(:application)).to eq(group_1_application_1) end it "re-renders the 'edit' template" do # Trigger the behavior that occurs when invalid params are submitted - patch :update, {id: group_1_application_1.to_param, - doorkeeper_application: { "redirect_uri" => "invalid" }}, valid_session + patch :update, params: {id: group_1_application_1.to_param, + doorkeeper_application: { "redirect_uri" => "invalid" }}, session: valid_session expect(response).to render_template("edit") end end @@ -156,12 +157,12 @@ module Oauth context "DELETE destroy" do it "destroys the requested application" do expect { - delete :destroy, {id: group_1_application_1.to_param}, admin_session + delete :destroy, params: {id: group_1_application_1.to_param}, session: admin_session }.to change(Doorkeeper::Application, :count).by(-1) end it "redirects to the applications list" do - delete :destroy, {id: group_1_application_1.to_param}, admin_session + delete :destroy, params: {id: group_1_application_1.to_param}, session: admin_session expect(response).to redirect_to(oauth_applications_url) end end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 98d4ead8..79dad655 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -7,7 +7,7 @@ first_name { Faker::Name.first_name } last_name { Faker::Name.last_name } full_name { "#{first_name} #{last_name}" } - title { Faker::Name.title } + title { Faker::Job.title } end after(:build) do |user, evaluator| diff --git a/spec/lib/publishable_spec.rb b/spec/lib/publishable_spec.rb index 7ff3661c..cd962d30 100644 --- a/spec/lib/publishable_spec.rb +++ b/spec/lib/publishable_spec.rb @@ -6,9 +6,11 @@ subject(:publishable) { FactoryBot.create :exercise } let(:author) { FactoryBot.create :user } + let(:coyright_holder) { FactoryBot.create :user } let(:user) { FactoryBot.create :user } - before { publishable.authors << Author.new(user: author) } + before { publishable.authors << Author.new(user: author) + publishable.copyright_holders << CopyrightHolder.new(user: author) } it 'can determine versions visible for a user' do p1 = publishable diff --git a/spec/models/administrator_spec.rb b/spec/models/administrator_spec.rb index a80b1e50..9882ca3a 100644 --- a/spec/models/administrator_spec.rb +++ b/spec/models/administrator_spec.rb @@ -6,8 +6,6 @@ it { is_expected.to belong_to(:user) } - it { is_expected.to validate_presence_of(:user) } - it { is_expected.to validate_uniqueness_of(:user) } end diff --git a/spec/models/answer_spec.rb b/spec/models/answer_spec.rb index bcd19753..12a960b2 100644 --- a/spec/models/answer_spec.rb +++ b/spec/models/answer_spec.rb @@ -6,7 +6,6 @@ it { is_expected.to have_many(:combo_choice_answers).dependent(:destroy) } - it { is_expected.to validate_presence_of(:question) } it { is_expected.to validate_presence_of(:content) } end diff --git a/spec/models/attachment_spec.rb b/spec/models/attachment_spec.rb index bcaa9442..10ee5924 100644 --- a/spec/models/attachment_spec.rb +++ b/spec/models/attachment_spec.rb @@ -9,8 +9,6 @@ it { is_expected.to belong_to(:parent) } - it { is_expected.to validate_presence_of(:parent) } - it 'requires a unique asset for each parent' do attachment_2 = FactoryBot.build :attachment, parent: attachment.parent, asset: nil expect(attachment_2).not_to be_valid diff --git a/spec/models/author_spec.rb b/spec/models/author_spec.rb index 76a7cd7d..b4b9cb75 100644 --- a/spec/models/author_spec.rb +++ b/spec/models/author_spec.rb @@ -7,9 +7,6 @@ it { is_expected.to belong_to(:publication) } it { is_expected.to belong_to(:user) } - it { is_expected.to validate_presence_of(:publication) } - it { is_expected.to validate_presence_of(:user) } - it { is_expected.to delegate_method(:name).to(:user) } it 'requires a unique user for each publication' do diff --git a/spec/models/class_license_spec.rb b/spec/models/class_license_spec.rb index 800874c7..a94d4aa0 100644 --- a/spec/models/class_license_spec.rb +++ b/spec/models/class_license_spec.rb @@ -6,7 +6,6 @@ it { is_expected.to belong_to(:license) } - it { is_expected.to validate_presence_of(:license) } it { is_expected.to validate_presence_of(:class_name) } it { is_expected.to validate_uniqueness_of(:class_name).scoped_to(:license_id) } diff --git a/spec/models/combo_choice_answer_spec.rb b/spec/models/combo_choice_answer_spec.rb index b1f612d8..ae65371c 100644 --- a/spec/models/combo_choice_answer_spec.rb +++ b/spec/models/combo_choice_answer_spec.rb @@ -7,9 +7,6 @@ it { is_expected.to belong_to(:combo_choice) } it { is_expected.to belong_to(:answer) } - it { is_expected.to validate_presence_of(:combo_choice) } - it { is_expected.to validate_presence_of(:answer) } - it { is_expected.to validate_uniqueness_of(:answer).scoped_to(:combo_choice_id) } it 'should require answer and combo_choice to have the same question' do diff --git a/spec/models/combo_choice_spec.rb b/spec/models/combo_choice_spec.rb index 6135bb22..5a9e227b 100644 --- a/spec/models/combo_choice_spec.rb +++ b/spec/models/combo_choice_spec.rb @@ -6,7 +6,6 @@ it { is_expected.to have_many(:combo_choice_answers).dependent(:destroy) } - it { is_expected.to validate_presence_of(:stem) } it { is_expected.to validate_presence_of(:correctness) } it { is_expected.to validate_numericality_of(:correctness) } diff --git a/spec/models/copyright_holder_spec.rb b/spec/models/copyright_holder_spec.rb index 00ac4373..ebb927f3 100644 --- a/spec/models/copyright_holder_spec.rb +++ b/spec/models/copyright_holder_spec.rb @@ -7,9 +7,6 @@ it { is_expected.to belong_to(:publication) } it { is_expected.to belong_to(:user) } - it { is_expected.to validate_presence_of(:publication) } - it { is_expected.to validate_presence_of(:user) } - it { is_expected.to delegate_method(:name).to(:user) } it 'requires a unique user for each publication' do diff --git a/spec/models/deputization_spec.rb b/spec/models/deputization_spec.rb index 2dbc0317..0b97c4cb 100644 --- a/spec/models/deputization_spec.rb +++ b/spec/models/deputization_spec.rb @@ -5,9 +5,6 @@ it { is_expected.to belong_to(:deputy) } it { is_expected.to belong_to(:deputizer) } - it { is_expected.to validate_presence_of(:deputy) } - it { is_expected.to validate_presence_of(:deputizer) } - it 'requires a unique deputizer for each deputy' do deputization_1 = FactoryBot.create :deputization deputization_2 = FactoryBot.build :deputization, diff --git a/spec/models/derivation_spec.rb b/spec/models/derivation_spec.rb index 63079537..912719ce 100644 --- a/spec/models/derivation_spec.rb +++ b/spec/models/derivation_spec.rb @@ -5,9 +5,7 @@ subject(:derivation) { FactoryBot.create :derivation } it { is_expected.to belong_to(:derived_publication) } - it { is_expected.to belong_to(:source_publication) } - - it { is_expected.to validate_presence_of(:derived_publication) } + it { is_expected.to belong_to(:source_publication).optional } it 'requires a unique source_publication for each derived_publication' do derivation_2 = FactoryBot.build(:derivation, diff --git a/spec/models/exercise_spec.rb b/spec/models/exercise_spec.rb index 7f9a75e6..ce1cdc68 100644 --- a/spec/models/exercise_spec.rb +++ b/spec/models/exercise_spec.rb @@ -14,7 +14,7 @@ expect(exercise.errors).to be_empty exercise.questions = [] - exercise.send :has_questions + expect { exercise.send :has_questions }.to throw_symbol(:abort) expect(exercise.errors[:questions]).to include("can't be blank") end @@ -26,7 +26,7 @@ exercise.questions.first.stems.first.stem_answers.each do |stem_answer| stem_answer.update_attribute :correctness, 0.0 end - exercise.before_publication + expect { exercise.before_publication }.to throw_symbol(:abort) expect(exercise.errors[:base]).to include('has a question with only incorrect answers') end diff --git a/spec/models/exercise_tag_spec.rb b/spec/models/exercise_tag_spec.rb index f7c27b89..85db1952 100644 --- a/spec/models/exercise_tag_spec.rb +++ b/spec/models/exercise_tag_spec.rb @@ -6,8 +6,5 @@ it { is_expected.to belong_to(:exercise) } it { is_expected.to belong_to(:tag) } - it { is_expected.to validate_presence_of(:exercise) } - it { is_expected.to validate_presence_of(:tag) } - it { is_expected.to validate_uniqueness_of(:tag).scoped_to(:exercise_id) } end diff --git a/spec/models/hint_spec.rb b/spec/models/hint_spec.rb index d761581e..7c7d06b2 100644 --- a/spec/models/hint_spec.rb +++ b/spec/models/hint_spec.rb @@ -4,7 +4,6 @@ it { is_expected.to belong_to(:question) } - it { is_expected.to validate_presence_of(:question) } it { is_expected.to validate_presence_of(:content) } end diff --git a/spec/models/license_compatibility_spec.rb b/spec/models/license_compatibility_spec.rb index 6998cb0e..4e0f1db7 100644 --- a/spec/models/license_compatibility_spec.rb +++ b/spec/models/license_compatibility_spec.rb @@ -7,9 +7,6 @@ it { is_expected.to belong_to(:original_license) } it { is_expected.to belong_to(:combined_license) } - it { is_expected.to validate_presence_of(:original_license) } - it { is_expected.to validate_presence_of(:combined_license) } - it { is_expected.to validate_uniqueness_of(:combined_license).scoped_to(:original_license_id) } end diff --git a/spec/models/list_editor_spec.rb b/spec/models/list_editor_spec.rb index 52ddde8f..cb0f505b 100644 --- a/spec/models/list_editor_spec.rb +++ b/spec/models/list_editor_spec.rb @@ -5,9 +5,6 @@ it { is_expected.to belong_to(:list) } it { is_expected.to belong_to(:editor) } - it { is_expected.to validate_presence_of(:list) } - it { is_expected.to validate_presence_of(:editor) } - it 'requires a unique editor for each list' do list_editor_1 = FactoryBot.create :list_editor list_editor_2 = FactoryBot.build :list_editor, diff --git a/spec/models/list_nesting_spec.rb b/spec/models/list_nesting_spec.rb index f39fb14f..d0abfbfe 100644 --- a/spec/models/list_nesting_spec.rb +++ b/spec/models/list_nesting_spec.rb @@ -7,9 +7,6 @@ it { is_expected.to belong_to(:parent_list) } it { is_expected.to belong_to(:child_list) } - it { is_expected.to validate_presence_of(:parent_list) } - it { is_expected.to validate_presence_of(:child_list) } - it { is_expected.to validate_uniqueness_of(:child_list) } end diff --git a/spec/models/list_owner_spec.rb b/spec/models/list_owner_spec.rb index d3a12966..d89b1a23 100644 --- a/spec/models/list_owner_spec.rb +++ b/spec/models/list_owner_spec.rb @@ -5,9 +5,6 @@ it { is_expected.to belong_to(:list) } it { is_expected.to belong_to(:owner) } - it { is_expected.to validate_presence_of(:list) } - it { is_expected.to validate_presence_of(:owner) } - it 'requires a unique owner for each list' do list_owner_1 = FactoryBot.create :list_owner list_owner_2 = FactoryBot.build :list_owner, diff --git a/spec/models/list_publication_group_spec.rb b/spec/models/list_publication_group_spec.rb index ce6a2625..37bbe45c 100644 --- a/spec/models/list_publication_group_spec.rb +++ b/spec/models/list_publication_group_spec.rb @@ -7,9 +7,6 @@ it { is_expected.to belong_to(:list) } it { is_expected.to belong_to(:publication_group) } - it { is_expected.to validate_presence_of(:list) } - it { is_expected.to validate_presence_of(:publication_group) } - it { is_expected.to validate_uniqueness_of(:publication_group).scoped_to(:list_id) } end diff --git a/spec/models/list_reader_spec.rb b/spec/models/list_reader_spec.rb index 4e6078c1..878b4a63 100644 --- a/spec/models/list_reader_spec.rb +++ b/spec/models/list_reader_spec.rb @@ -5,9 +5,6 @@ it { is_expected.to belong_to(:list) } it { is_expected.to belong_to(:reader) } - it { is_expected.to validate_presence_of(:list) } - it { is_expected.to validate_presence_of(:reader) } - it 'requires a unique reader for each list' do list_reader_1 = FactoryBot.create :list_reader list_reader_2 = FactoryBot.build :list_reader, diff --git a/spec/models/logic_spec.rb b/spec/models/logic_spec.rb index 25ec3dee..2cc015dd 100644 --- a/spec/models/logic_spec.rb +++ b/spec/models/logic_spec.rb @@ -6,7 +6,6 @@ it { is_expected.to have_many(:logic_variables) } - it { is_expected.to validate_presence_of(:parent) } it { is_expected.to validate_presence_of(:language) } it { is_expected.to validate_presence_of(:code) } diff --git a/spec/models/logic_variable_spec.rb b/spec/models/logic_variable_spec.rb index 5c2f005b..e8d6b49f 100644 --- a/spec/models/logic_variable_spec.rb +++ b/spec/models/logic_variable_spec.rb @@ -11,7 +11,6 @@ it { is_expected.to have_many(:logic_variable_values).dependent(:destroy) } - it { is_expected.to validate_presence_of(:logic) } it { is_expected.to validate_presence_of(:variable) } it { is_expected.to validate_uniqueness_of(:variable).scoped_to(:logic_id) } diff --git a/spec/models/logic_variable_value_spec.rb b/spec/models/logic_variable_value_spec.rb index 04d67ddd..8a2cd31c 100644 --- a/spec/models/logic_variable_value_spec.rb +++ b/spec/models/logic_variable_value_spec.rb @@ -6,7 +6,6 @@ it { is_expected.to belong_to(:logic_variable) } - it { is_expected.to validate_presence_of(:logic_variable) } it { is_expected.to validate_presence_of(:seed) } it { is_expected.to validate_presence_of(:value) } diff --git a/spec/models/publication_spec.rb b/spec/models/publication_spec.rb index 9d1c0cfd..3640af62 100644 --- a/spec/models/publication_spec.rb +++ b/spec/models/publication_spec.rb @@ -6,7 +6,7 @@ it { is_expected.to belong_to(:publication_group) } it { is_expected.to belong_to(:publishable) } - it { is_expected.to belong_to(:license) } + it { is_expected.to belong_to(:license).optional } it { is_expected.to have_many(:authors).dependent(:destroy) } it { is_expected.to have_many(:copyright_holders).dependent(:destroy) } @@ -14,9 +14,6 @@ it { is_expected.to have_many(:sources).dependent(:destroy) } it { is_expected.to have_many(:derivations).dependent(:destroy) } - it { is_expected.to validate_presence_of(:publication_group) } - it { is_expected.to validate_presence_of(:publishable) } - it { is_expected.to validate_uniqueness_of(:uuid).case_insensitive } it { is_expected.to validate_uniqueness_of(:version).scoped_to(:publication_group_id) } @@ -96,7 +93,7 @@ it 'validates the publishable before publication' do expect(publication.reload.publishable).to receive(:before_publication) do publication.publishable.errors.add(:base, 'is invalid') - false + throw :abort end expect(publication.publish.save).to eq false expect(publication.errors.first).to eq [:exercise, 'is invalid'] diff --git a/spec/models/question_dependency_spec.rb b/spec/models/question_dependency_spec.rb index c2112c3f..a77e98eb 100644 --- a/spec/models/question_dependency_spec.rb +++ b/spec/models/question_dependency_spec.rb @@ -7,9 +7,6 @@ it { is_expected.to belong_to(:parent_question) } it { is_expected.to belong_to(:dependent_question) } - it { is_expected.to validate_presence_of(:parent_question) } - it { is_expected.to validate_presence_of(:dependent_question) } - it { is_expected.to validate_uniqueness_of(:dependent_question).scoped_to(:parent_question_id) } it 'requires both questions to belong to the same exercise' do diff --git a/spec/models/question_spec.rb b/spec/models/question_spec.rb index 723253cf..55b8ed26 100644 --- a/spec/models/question_spec.rb +++ b/spec/models/question_spec.rb @@ -12,6 +12,6 @@ it { is_expected.to have_many(:parent_dependencies).dependent(:destroy) } it { is_expected.to have_many(:child_dependencies).dependent(:destroy) } - it { is_expected.to validate_presence_of(:exercise) } + it { is_expected.to belong_to(:exercise) } end diff --git a/spec/models/stem_answer_spec.rb b/spec/models/stem_answer_spec.rb index f48243f7..fbd8b650 100644 --- a/spec/models/stem_answer_spec.rb +++ b/spec/models/stem_answer_spec.rb @@ -7,8 +7,6 @@ it { is_expected.to belong_to(:stem) } it { is_expected.to belong_to(:answer) } - it { is_expected.to validate_presence_of(:stem) } - it { is_expected.to validate_presence_of(:answer) } it { is_expected.to validate_presence_of(:correctness) } it { is_expected.to validate_uniqueness_of(:answer).scoped_to(:stem_id) } diff --git a/spec/models/stem_spec.rb b/spec/models/stem_spec.rb index 896a0ee1..2e0883a7 100644 --- a/spec/models/stem_spec.rb +++ b/spec/models/stem_spec.rb @@ -8,7 +8,6 @@ it { is_expected.to have_many(:combo_choices).dependent(:destroy) } - it { is_expected.to validate_presence_of(:question) } it { is_expected.to validate_presence_of(:content) } end diff --git a/spec/models/styling_spec.rb b/spec/models/styling_spec.rb index 2868daa2..2c6ac1c1 100644 --- a/spec/models/styling_spec.rb +++ b/spec/models/styling_spec.rb @@ -4,7 +4,6 @@ it { is_expected.to belong_to(:stylable) } - it { is_expected.to validate_presence_of(:stylable) } it { is_expected.to validate_presence_of(:style) } it { is_expected.to validate_inclusion_of(:style).in_array(Style.all) } diff --git a/spec/models/trusted_application_spec.rb b/spec/models/trusted_application_spec.rb index 790144dd..0a4e84ae 100644 --- a/spec/models/trusted_application_spec.rb +++ b/spec/models/trusted_application_spec.rb @@ -6,8 +6,6 @@ it { is_expected.to belong_to(:application) } - it { is_expected.to validate_presence_of(:application) } - it { is_expected.to validate_uniqueness_of(:application) } end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index f7f90883..f16862f3 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -23,8 +23,6 @@ it { is_expected.to have_many(:direct_applications).dependent(:destroy) } - it { is_expected.to validate_presence_of(:account) } - it { is_expected.to validate_uniqueness_of(:account) } [ :username, :first_name, :last_name, :full_name, diff --git a/spec/models/vocab_distractor_spec.rb b/spec/models/vocab_distractor_spec.rb index 06d49db0..849ad0d9 100644 --- a/spec/models/vocab_distractor_spec.rb +++ b/spec/models/vocab_distractor_spec.rb @@ -5,8 +5,7 @@ it { is_expected.to belong_to(:vocab_term) } - it { is_expected.to validate_presence_of(:vocab_term) } - it { is_expected.to validate_presence_of(:distractor_publication_group) } + it { is_expected.to belong_to(:distractor_publication_group) } it { is_expected.to validate_presence_of(:distractor_term) } it do diff --git a/spec/models/vocab_term_spec.rb b/spec/models/vocab_term_spec.rb index 7c4a544d..01be958b 100644 --- a/spec/models/vocab_term_spec.rb +++ b/spec/models/vocab_term_spec.rb @@ -24,7 +24,7 @@ expect(vocab_term.errors).to be_empty vocab_term.definition = '' - vocab_term.before_publication + expect { vocab_term.before_publication }.to throw_symbol(:abort) expect(vocab_term.errors[:base]).to include('must have a definition') end @@ -39,7 +39,7 @@ expect(vocab_term.errors).to be_empty vocab_term.distractor_literals = [] - vocab_term.before_publication + expect { vocab_term.before_publication }.to throw_symbol(:abort) expect(vocab_term.errors[:base]).to include('must have at least 1 distractor') end diff --git a/spec/models/vocab_term_tag_spec.rb b/spec/models/vocab_term_tag_spec.rb index c6ae378f..ca727845 100644 --- a/spec/models/vocab_term_tag_spec.rb +++ b/spec/models/vocab_term_tag_spec.rb @@ -6,8 +6,5 @@ it { is_expected.to belong_to(:vocab_term) } it { is_expected.to belong_to(:tag) } - it { is_expected.to validate_presence_of(:vocab_term) } - it { is_expected.to validate_presence_of(:tag) } - it { is_expected.to validate_uniqueness_of(:tag).scoped_to(:vocab_term_id) } end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index e2623a92..37ae970a 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -20,9 +20,6 @@ end end -# Remove after dropping support of Rails 4.2 -require "#{File.dirname(__FILE__)}/support/ruby_2_6_rails_4_2_patch" - # 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 diff --git a/spec/routines/search_exercises_spec.rb b/spec/routines/search_exercises_spec.rb index 94549879..f2d53de3 100644 --- a/spec/routines/search_exercises_spec.rb +++ b/spec/routines/search_exercises_spec.rb @@ -6,14 +6,21 @@ 10.times { FactoryBot.create(:exercise, :published) } + ex = Exercise.arel_table + qu = Question.arel_table + st = Stem.arel_table + ans = Answer.arel_table + tested_strings = [ "%adipisci%", "%draft%" ] - Exercise.joins {questions.outer.stems.outer} - .joins {questions.outer.answers.outer} - .where {(title.like_any tested_strings) |\ - (stimulus.like_any tested_strings) |\ - (questions.stimulus.like_any tested_strings) |\ - (stems.content.like_any tested_strings) |\ - (answers.content.like_any tested_strings)}.delete_all + + ex_ids = Exercise.left_joins(questions: [:stems, :answers]).where( + ex[:title].matches_any(tested_strings) + .or(ex[:stimulus].matches_any(tested_strings)) + .or(qu[:stimulus].matches_any(tested_strings)) + .or(st[:content].matches_any(tested_strings)) + .or(ans[:content].matches_any(tested_strings))).pluck(:id) + + Exercise.where(id: ex_ids).delete_all @exercise_1 = Exercise.new Api::V1::Exercises::Representer.new(@exercise_1).from_hash( @@ -91,6 +98,7 @@ it "returns drafts that the user is allowed to see" do user = FactoryBot.create :user @exercise_draft.publication.authors << Author.new(user: user) + @exercise_draft.publication.copyright_holders << CopyrightHolder.new(user: user) @exercise_draft.reload result = described_class.call({q: 'content:draft'}, user: user.reload) expect(result.errors).to be_empty diff --git a/spec/routines/search_vocab_terms_spec.rb b/spec/routines/search_vocab_terms_spec.rb index 07242a94..f1ab9d55 100644 --- a/spec/routines/search_vocab_terms_spec.rb +++ b/spec/routines/search_vocab_terms_spec.rb @@ -7,8 +7,10 @@ 10.times { FactoryBot.create(:vocab_term, :published) } tested_strings = ["%lorem ipsu%", "%uia dolor sit ame%", "%adipiscing elit%", "draft"] - VocabTerm.where {(name.like_any tested_strings) | - (definition.like_any tested_strings)}.delete_all + + vt = VocabTerm.arel_table + VocabTerm.where(vt[:name].matches_any(tested_strings).or( + vt[:definition].matches_any(tested_strings))).delete_all @vocab_term_1 = FactoryBot.build(:vocab_term, :published) Api::V1::Vocabs::TermWithDistractorsAndExerciseIdsRepresenter.new(@vocab_term_1).from_hash( @@ -67,6 +69,7 @@ it "returns drafts that the user is allowed to see" do user = FactoryBot.create :user @vocab_term_draft.publication.authors << Author.new(user: user) + @vocab_term_draft.publication.copyright_holders << CopyrightHolder.new(user: user) @vocab_term_draft.reload result = described_class.call({q: 'content:draft'}, user: user) expect(result.errors).to be_empty diff --git a/spec/support/ruby_2_6_rails_4_2_patch.rb b/spec/support/ruby_2_6_rails_4_2_patch.rb deleted file mode 100644 index 1e1d9f98..00000000 --- a/spec/support/ruby_2_6_rails_4_2_patch.rb +++ /dev/null @@ -1,14 +0,0 @@ -if RUBY_VERSION >= '2.6.0' - if Rails::VERSION::MAJOR < 5 - class ActionController::TestResponse < ActionDispatch::TestResponse - def recycle! - # hack to avoid MonitorMixin double-initialize error: - @mon_mutex_owner_object_id = nil - @mon_mutex = nil - initialize - end - end - else - puts "Monkeypatch for ActionController::TestResponse no longer needed" - end -end