From 913da36f51d495908125fcb02e769ad67ca725f8 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Thu, 28 Jan 2016 21:40:04 +0800 Subject: [PATCH 01/19] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E5=88=B0=20Rails=205?= =?UTF-8?q?=EF=BC=8C=E5=B9=B6=E4=BF=AE=E6=AD=A3=E5=90=84=E7=A7=8D=E9=97=AE?= =?UTF-8?q?=E9=A2=98;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile | 79 +-- Gemfile.lock | 383 +++++++------ Gemfile1.lock | 519 ++++++++++++++++++ app/controllers/topics_controller.rb | 1 - app/jobs/application_job.rb | 2 + app/jobs/github_repo_fetcher_job.rb | 2 +- app/jobs/notify_reply_job.rb | 2 +- app/jobs/notify_topic_job.rb | 2 +- app/jobs/search_indexer.rb | 2 +- app/models/application_record.rb | 3 + app/models/authorization.rb | 2 +- app/models/comment.rb | 2 +- app/models/concerns/base_model.rb | 36 +- app/models/exception_log.rb | 2 +- app/models/location.rb | 2 +- app/models/node.rb | 2 +- app/models/note.rb | 2 +- app/models/notification/base.rb | 2 +- app/models/page.rb | 2 +- app/models/page_version.rb | 2 +- app/models/photo.rb | 2 +- app/models/reply.rb | 2 +- app/models/section.rb | 2 +- app/models/site.rb | 2 +- app/models/site_node.rb | 2 +- app/models/topic.rb | 2 +- app/models/user.rb | 15 +- bin/provision.sh | 0 bin/setup | 2 +- bin/update | 29 + config.ru | 6 +- config/application.rb | 38 +- config/config.yml.default | 2 +- config/environments/development.rb | 48 +- config/environments/production.rb | 68 +-- config/environments/test.rb | 10 +- .../application_controller_renderer.rb | 6 + config/initializers/assets.rb | 4 + config/initializers/cookies_serializer.rb | 4 +- config/initializers/cors.rb | 16 + config/initializers/devise.rb | 2 - config/initializers/inflections.rb | 12 +- .../request_forgery_protection.rb | 4 + config/initializers/session_store.rb | 5 - config/initializers/wrap_parameters.rb | 2 +- config/locales/en.yml | 30 +- config/redis/cable.yml | 9 + config/routes.rb | 12 +- db/migrate/20160126061903_create_settings.rb | 2 +- lib/api/v3/root.rb | 2 +- spec/models/concerns/base_model_spec.rb | 2 +- spec/models/concerns/mentionable_spec.rb | 2 +- spec/models/concerns/soft_delete_spec.rb | 2 +- spec/support/api_v3_support.rb | 2 +- 54 files changed, 1045 insertions(+), 352 deletions(-) create mode 100644 Gemfile1.lock create mode 100644 app/jobs/application_job.rb create mode 100644 app/models/application_record.rb mode change 100644 => 100755 bin/provision.sh create mode 100755 bin/update create mode 100644 config/initializers/application_controller_renderer.rb create mode 100644 config/initializers/cors.rb create mode 100644 config/initializers/request_forgery_protection.rb create mode 100644 config/redis/cable.yml diff --git a/Gemfile b/Gemfile index 0ab555417f..32203fa32b 100644 --- a/Gemfile +++ b/Gemfile @@ -6,19 +6,18 @@ end ruby '2.3.0' -gem 'rails', '4.2.5.1' +gem 'rails', '5.0.0.beta1.1' gem 'sprockets' gem 'sass-rails' gem 'coffee-rails' gem 'uglifier' gem 'jquery-rails' gem 'jbuilder' -gem 'turbolinks', git: 'https://github.com/rails/turbolinks.git' +gem 'turbolinks', github: 'rails/turbolinks' gem 'jquery-turbolinks' gem 'dropzonejs-rails' -gem 'actionpack-action_caching' -gem 'rails-i18n' +gem 'rails-i18n', '~> 5.0.0.beta1' gem 'http_accept_language' gem 'rails_autolink' gem 'md_emoji' @@ -27,11 +26,11 @@ gem 'exception_notification' gem 'doorkeeper', '~> 2.2.1' gem 'doorkeeper-i18n' -gem 'rails-perftest' -gem 'ruby-prof' +# gem 'rails-perftest' +# gem 'ruby-prof' # 上传组件 -gem 'carrierwave', '~> 0.10.0' +gem 'carrierwave' gem 'carrierwave-upyun' gem 'mini_magick' @@ -39,14 +38,12 @@ gem 'rucaptcha' gem 'letter_avatar' gem 'pg' -gem 'activerecord_any_of' # remove this after migrate MongoDB into PostgreSQL gem 'mongo', require: false # 用户系统 -gem 'devise', '~> 3.5.1' -gem 'devise-async' +gem 'devise', github: 'plataformatec/devise' gem 'devise-encryptable' # 分页 @@ -57,57 +54,57 @@ gem 'elasticsearch-model' gem 'elasticsearch-rails' # 三方平台 OAuth 验证登陆 -gem 'omniauth', '~> 1.2.2' -gem 'omniauth-github', '~> 1.1.0' +gem 'omniauth' +gem 'omniauth-github' # permission gem 'cancancan', '~> 1.8.4' -gem 'redis', '~> 3.2.1' -gem 'hiredis', '~> 0.6.0' +gem 'redis' +gem 'hiredis' # Redis 命名空间 -gem 'redis-namespace', '~> 1.5.1' +gem 'redis-namespace' # 将一些数据存放入 Redis -gem 'redis-objects', '1.1.0' +gem 'redis-objects' gem 'rails-settings-cached' # Markdown 格式 & 文本处理 gem 'redcarpet', '~> 3.3.4' gem 'rouge', '~> 1.8.0' -gem 'auto-space', '0.0.4' +gem 'auto-space' gem 'nokogiri' # YAML 配置信息 -gem 'settingslogic', '~> 2.0.9' +gem 'settingslogic' # 队列 gem 'sidekiq' # Sidekiq Web -gem 'sinatra', require: nil +# gem 'sinatra', require: nil gem 'message_bus' # 分享功能 -gem 'social-share-button', '0.1.5' +gem 'social-share-button' # 表单 -gem 'simple_form', '3.1.0' +gem 'simple_form' # API -gem 'grape', '0.7.0' -gem 'active_model_serializers' +gem 'grape' +gem 'active_model_serializers', '0.9.2' gem 'grape-active_model_serializers' # Mailer -gem 'postmark', '0.9.15' -gem 'postmark-rails', '0.4.1' +gem 'postmark' +gem 'postmark-rails' # Dalli, kgio is for Dalli gem 'kgio' -gem 'dalli', '2.7.4' +gem 'dalli' -gem 'unicorn', '5.0.0' +gem 'unicorn' gem 'parallel' @@ -121,32 +118,38 @@ gem 'rack-mini-profiler', require: false gem 'oneapm_rpm' group :development do - gem 'derailed' -end + gem 'puma' -group :development, :test do gem 'capistrano', '2.9.0', require: false gem 'capistrano-unicorn' gem 'rvm-capistrano', require: false gem 'capistrano-sidekiq' + gem 'derailed' + + # Better Errors + gem 'better_errors' + gem 'binding_of_caller' +end + +group :development, :test do gem 'rubocop' - gem 'rspec-rails', '~> 3.4' + + gem 'rspec-rails', github: 'rspec/rspec-rails' + gem 'rspec-mocks', github: 'rspec/rspec-mocks' + gem 'rspec-core', github: 'rspec/rspec-core' + gem 'rspec-support', github: 'rspec/rspec-support' + gem 'rspec-expectations', github: 'rspec/rspec-expectations' + gem 'rspec', github: 'rspec/rspec' + gem 'factory_girl_rails', '~> 4.5.0' gem 'database_cleaner' gem 'capybara', '~> 2.3.0' - gem 'api_taster', '0.6.0' gem 'jasmine-rails', '~> 0.10.2' gem 'colorize' gem 'letter_opener' - gem 'puma', '~> 2.14.0' - - # Better Errors - gem 'better_errors' - gem 'binding_of_caller' - gem 'bundler-audit', require: false end diff --git a/Gemfile.lock b/Gemfile.lock index d8c8953364..6f166bdd68 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,63 +1,123 @@ GIT - remote: https://github.com/rails/turbolinks.git - revision: 37e097d24763106a7a3f06c5ec0b6242cff18ea2 + remote: git://github.com/plataformatec/devise.git + revision: cf7c9be6b4129088f9b6457cecf64c6e2a2e0f11 + specs: + devise (4.0.0.pre.dev) + bcrypt (~> 3.0) + orm_adapter (~> 0.1) + railties (>= 4.1.0, < 5.1) + responders + warden (~> 1.2.3) + +GIT + remote: git://github.com/rails/turbolinks.git + revision: dd31f4b2996f2300631f89339ada82c65b95f4c2 specs: turbolinks (3.0.0) coffee-rails +GIT + remote: git://github.com/rspec/rspec-core.git + revision: e9b99468cbfa45d2c0f38e69a0c9c9184814e327 + specs: + rspec-core (3.5.0.pre) + rspec-support (= 3.5.0.pre) + +GIT + remote: git://github.com/rspec/rspec-expectations.git + revision: e7b08da715a777320586dec9f6c2ae5c44585ddd + specs: + rspec-expectations (3.5.0.pre) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (= 3.5.0.pre) + +GIT + remote: git://github.com/rspec/rspec-mocks.git + revision: 2fcdbaee682efc35c146c9f713c079356ca3ec6e + specs: + rspec-mocks (3.5.0.pre) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (= 3.5.0.pre) + +GIT + remote: git://github.com/rspec/rspec-rails.git + revision: 44e5b8a927c35397bdbf36a6a99fbb9a567f25b8 + specs: + rspec-rails (3.5.0.pre) + actionpack (>= 3.0) + activesupport (>= 3.0) + railties (>= 3.0) + rspec-core (= 3.5.0.pre) + rspec-expectations (= 3.5.0.pre) + rspec-mocks (= 3.5.0.pre) + rspec-support (= 3.5.0.pre) + +GIT + remote: git://github.com/rspec/rspec-support.git + revision: 4b938ec512d2fbee945913afbb957b510244ecb3 + specs: + rspec-support (3.5.0.pre) + +GIT + remote: git://github.com/rspec/rspec.git + revision: 5966b248d83a74c58784ff195cef5d6be22fa17c + specs: + rspec (3.5.0.pre) + rspec-core (= 3.5.0.pre) + rspec-expectations (= 3.5.0.pre) + rspec-mocks (= 3.5.0.pre) + GEM remote: https://ruby.taobao.org/ specs: - actionmailer (4.2.5.1) - actionpack (= 4.2.5.1) - actionview (= 4.2.5.1) - activejob (= 4.2.5.1) + actioncable (5.0.0.beta1.1) + actionpack (= 5.0.0.beta1.1) + celluloid (~> 0.17.2) + coffee-rails (~> 4.1.0) + em-hiredis (~> 0.3.0) + faye-websocket (~> 0.10.0) + redis (~> 3.0) + websocket-driver (~> 0.6.1) + actionmailer (5.0.0.beta1.1) + actionpack (= 5.0.0.beta1.1) + actionview (= 5.0.0.beta1.1) + activejob (= 5.0.0.beta1.1) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.5.1) - actionview (= 4.2.5.1) - activesupport (= 4.2.5.1) - rack (~> 1.6) - rack-test (~> 0.6.2) + actionpack (5.0.0.beta1.1) + actionview (= 5.0.0.beta1.1) + activesupport (= 5.0.0.beta1.1) + rack (~> 2.x) + rack-test (~> 0.6.3) rails-dom-testing (~> 1.0, >= 1.0.5) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionpack-action_caching (1.1.1) - actionpack (>= 4.0.0, < 5.0) - actionview (4.2.5.1) - activesupport (= 4.2.5.1) + actionview (5.0.0.beta1.1) + activesupport (= 5.0.0.beta1.1) builder (~> 3.1) erubis (~> 2.7.0) rails-dom-testing (~> 1.0, >= 1.0.5) rails-html-sanitizer (~> 1.0, >= 1.0.2) - active_model_serializers (0.9.3) + active_model_serializers (0.9.2) activemodel (>= 3.2) - activejob (4.2.5.1) - activesupport (= 4.2.5.1) - globalid (>= 0.3.0) - activemodel (4.2.5.1) - activesupport (= 4.2.5.1) + activejob (5.0.0.beta1.1) + activesupport (= 5.0.0.beta1.1) + globalid (>= 0.3.6) + activemodel (5.0.0.beta1.1) + activesupport (= 5.0.0.beta1.1) builder (~> 3.1) - activerecord (4.2.5.1) - activemodel (= 4.2.5.1) - activesupport (= 4.2.5.1) - arel (~> 6.0) - activerecord_any_of (1.3) - activerecord (>= 3.2.13, < 5) - activesupport (4.2.5.1) + activerecord (5.0.0.beta1.1) + activemodel (= 5.0.0.beta1.1) + activesupport (= 5.0.0.beta1.1) + arel (~> 7.0) + activesupport (5.0.0.beta1.1) + concurrent-ruby (~> 1.0) i18n (~> 0.7) json (~> 1.7, >= 1.7.7) + method_source minitest (~> 5.1) - thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) addressable (2.4.0) - api_taster (0.6.0) - bootstrap-sass (~> 2.1) - jquery-rails - rails (>= 3.1.0) - redcarpet - remotipart (~> 1.0) - sass-rails - arel (6.0.3) + arel (7.0.0) ast (2.2.0) auto-space (0.0.4) activesupport (> 3.0.0) @@ -73,9 +133,7 @@ GEM rack (>= 0.9.0) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) - bootstrap-sass (2.3.2.2) - sass (~> 3.2) - bson (4.0.0) + bson (4.0.1) builder (3.2.2) bundler-audit (0.4.0) bundler (~> 1.2) @@ -106,6 +164,23 @@ GEM carrierwave-upyun (0.2.1) carrierwave (>= 0.5.7) faraday (>= 0.8.0) + celluloid (0.17.3) + celluloid-essentials + celluloid-extras + celluloid-fsm + celluloid-pool + celluloid-supervision + timers (>= 4.1.1) + celluloid-essentials (0.20.5) + timers (>= 4.1.1) + celluloid-extras (0.20.5) + timers (>= 4.1.1) + celluloid-fsm (0.20.5) + timers (>= 4.1.1) + celluloid-pool (0.20.5) + timers (>= 4.1.1) + celluloid-supervision (0.20.5) + timers (>= 4.1.1) coderay (1.1.0) coercible (1.0.0) descendants_tracker (~> 0.0.1) @@ -119,30 +194,21 @@ GEM colorize (0.7.7) concurrent-ruby (1.0.0) connection_pool (2.2.0) - dalli (2.7.4) + dalli (2.7.5) database_cleaner (1.5.1) debug_inspector (0.0.2) derailed (0.1.0) derailed_benchmarks - derailed_benchmarks (1.1.3) + derailed_benchmarks (1.3.0) benchmark-ips (~> 2) get_process_mem (~> 0) heapy (~> 0) memory_profiler (~> 0) - rack (~> 1) + rack (>= 1) rake (~> 10) thor (~> 0.19) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) - devise (3.5.4) - bcrypt (~> 3.0) - orm_adapter (~> 0.1) - railties (>= 3.2.6, < 5) - responders - thread_safe (~> 0.1) - warden (~> 1.2.3) - devise-async (0.10.1) - devise (~> 3.2) devise-encryptable (0.2.0) devise (>= 2.1.0) diff-lcs (1.2.5) @@ -164,11 +230,15 @@ GEM elasticsearch-transport (1.0.15) faraday multi_json + em-hiredis (0.3.0) + eventmachine (~> 1.0) + hiredis (~> 0.5.0) equalizer (0.0.11) erubis (2.7.0) - exception_notification (4.1.3) - actionmailer (~> 4.0) - activesupport (~> 4.0) + eventmachine (1.0.9.1) + exception_notification (4.1.1) + actionmailer (>= 3.0.4) + activesupport (>= 3.0.4) execjs (2.6.0) factory_girl (4.5.0) activesupport (>= 3.0.0) @@ -177,13 +247,16 @@ GEM railties (>= 3.0.0) faraday (0.9.2) multipart-post (>= 1.2, < 3) + faye-websocket (0.10.2) + eventmachine (>= 0.12.0) + websocket-driver (>= 0.5.1) get_process_mem (0.2.0) globalid (0.3.6) activesupport (>= 4.1.0) - grape (0.7.0) + grape (0.14.0) activesupport builder - hashie (>= 1.2.0) + hashie (>= 2.1.0) multi_json (>= 1.3.2) multi_xml (>= 0.5.2) rack (>= 1.3.0) @@ -196,8 +269,10 @@ GEM hashie (3.4.3) heapy (0.1.2) highline (1.7.8) - hiredis (0.6.1) + hiredis (0.5.2) + hitimes (1.2.3) http_accept_language (2.0.5) + httpauth (0.2.1) i18n (0.7.0) ice_nine (0.11.1) jasmine-core (2.4.1) @@ -209,7 +284,7 @@ GEM jbuilder (2.4.0) activesupport (>= 3.0.0, < 5.1) multi_json (~> 1.2) - jquery-rails (4.0.5) + jquery-rails (4.1.0) rails-dom-testing (~> 1.0) railties (>= 4.2.0) thor (>= 0.14, < 2.0) @@ -217,7 +292,6 @@ GEM railties (>= 3.1.0) turbolinks json (1.8.3) - jwt (1.5.2) kgio (2.10.0) launchy (2.4.3) addressable (~> 2.3) @@ -235,11 +309,12 @@ GEM message_bus (1.1.1) rack (>= 1.1.3) redis + method_source (0.8.2) mime-types (2.99) mini_magick (4.3.6) mini_portile2 (2.0.0) minitest (5.8.4) - mongo (2.2.1) + mongo (2.2.2) bson (~> 4.0) multi_json (1.11.2) multi_xml (0.5.5) @@ -248,44 +323,42 @@ GEM net-ssh (>= 2.6.5) net-sftp (2.1.2) net-ssh (>= 2.6.5) - net-ssh (3.0.1) + net-ssh (3.0.2) net-ssh-gateway (1.2.0) net-ssh (>= 2.6.5) nokogiri (1.6.7.2) mini_portile2 (~> 2.0.0.rc2) - oauth2 (1.0.0) - faraday (>= 0.8, < 0.10) - jwt (~> 1.0) + oauth2 (0.6.1) + faraday (~> 0.7) + httpauth (~> 0.1) multi_json (~> 1.3) - multi_xml (~> 0.5) - rack (~> 1.2) - omniauth (1.2.2) + omniauth (1.3.1) hashie (>= 1.2, < 4) - rack (~> 1.0) - omniauth-github (1.1.2) + rack (>= 1.0, < 3) + omniauth-github (1.0.1) + omniauth (~> 1.0) + omniauth-oauth2 (~> 1.0) + omniauth-oauth2 (1.0.2) + oauth2 (~> 0.6.0) omniauth (~> 1.0) - omniauth-oauth2 (~> 1.1) - omniauth-oauth2 (1.4.0) - oauth2 (~> 1.0) - omniauth (~> 1.2) - oneapm_rpm (1.3.3) + oneapm_rpm (1.3.4) orm_adapter (0.5.0) parallel (1.6.1) - parser (2.3.0.1) + parser (2.3.0.2) ast (~> 2.2) pg (0.18.4) phantomjs (1.9.8.0) posix-spawn (0.3.11) - postmark (0.9.15) + postmark (1.7.0) json rake - postmark-rails (0.4.1) - actionmailer - postmark (>= 0.9.0) - rake + postmark-rails (0.12.0) + actionmailer (>= 3.0.0) + postmark (~> 1.7.0) powerpack (0.1.1) - puma (2.14.0) - rack (1.6.4) + puma (2.15.3) + rack (2.0.0.alpha) + json rack-accept (0.4.5) rack (>= 0.4) rack-cors (0.4.0) @@ -293,23 +366,22 @@ GEM rack (>= 1.1.3) rack-mount (0.8.3) rack (>= 1.0.0) - rack-protection (1.5.3) - rack rack-test (0.6.3) rack (>= 1.0) rack-utf8_sanitizer (1.3.2) rack (>= 1.0, < 3.0) - rails (4.2.5.1) - actionmailer (= 4.2.5.1) - actionpack (= 4.2.5.1) - actionview (= 4.2.5.1) - activejob (= 4.2.5.1) - activemodel (= 4.2.5.1) - activerecord (= 4.2.5.1) - activesupport (= 4.2.5.1) + rails (5.0.0.beta1.1) + actioncable (= 5.0.0.beta1.1) + actionmailer (= 5.0.0.beta1.1) + actionpack (= 5.0.0.beta1.1) + actionview (= 5.0.0.beta1.1) + activejob (= 5.0.0.beta1.1) + activemodel (= 5.0.0.beta1.1) + activerecord (= 5.0.0.beta1.1) + activesupport (= 5.0.0.beta1.1) bundler (>= 1.3.0, < 2.0) - railties (= 4.2.5.1) - sprockets-rails + railties (= 5.0.0.beta1.1) + sprockets-rails (>= 2.0.0) rails-deprecated_sanitizer (1.0.3) activesupport (>= 4.2.0.alpha) rails-dom-testing (1.0.7) @@ -318,61 +390,42 @@ GEM rails-deprecated_sanitizer (>= 1.0.1) rails-html-sanitizer (1.0.3) loofah (~> 2.0) - rails-i18n (4.0.8) + rails-i18n (5.0.0.beta2) i18n (~> 0.7) - railties (~> 4.0) - rails-perftest (0.0.6) + railties (~> 5.0.0.beta1) rails-settings-cached (0.5.3) rails (>= 4.2.0) rails_autolink (1.1.6) rails (> 3.1) - railties (4.2.5.1) - actionpack (= 4.2.5.1) - activesupport (= 4.2.5.1) + railties (5.0.0.beta1.1) + actionpack (= 5.0.0.beta1.1) + activesupport (= 5.0.0.beta1.1) + method_source rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rainbow (2.0.0) + rainbow (2.1.0) raindrops (0.15.0) rake (10.5.0) redcarpet (3.3.4) redis (3.2.2) redis-namespace (1.5.2) redis (~> 3.0, >= 3.0.4) - redis-objects (1.1.0) + redis-objects (1.2.1) redis (>= 3.0.2) - remotipart (1.2.1) responders (2.1.1) railties (>= 4.2.0, < 5.1) rouge (1.8.0) - rspec-core (3.4.1) - rspec-support (~> 3.4.0) - rspec-expectations (3.4.0) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.4.0) - rspec-mocks (3.4.0) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.4.0) - rspec-rails (3.4.0) - actionpack (>= 3.0, < 4.3) - activesupport (>= 3.0, < 4.3) - railties (>= 3.0, < 4.3) - rspec-core (~> 3.4.0) - rspec-expectations (~> 3.4.0) - rspec-mocks (~> 3.4.0) - rspec-support (~> 3.4.0) - rspec-support (3.4.1) rubocop (0.36.0) parser (>= 2.3.0.0, < 3.0) powerpack (~> 0.1) rainbow (>= 1.99.1, < 3.0) ruby-progressbar (~> 1.7) - ruby-prof (0.15.9) ruby-progressbar (1.7.5) rucaptcha (0.3.2) posix-spawn (>= 0.3.0) rvm-capistrano (1.4.1) capistrano (>= 2.0.0) - sass (3.4.20) + sass (3.4.21) sass-rails (5.0.4) railties (>= 4.0.0, < 5.0) sass (~> 3.1) @@ -380,19 +433,16 @@ GEM sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) settingslogic (2.0.9) - sidekiq (4.0.1) + sidekiq (4.0.2) concurrent-ruby (~> 1.0) connection_pool (~> 2.2, >= 2.2.0) - json (~> 1.0) redis (~> 3.2, >= 3.2.1) - simple_form (3.1.0) - actionpack (~> 4.0) - activemodel (~> 4.0) - sinatra (1.4.6) - rack (~> 1.4) - rack-protection (~> 1.4) - tilt (>= 1.3, < 3) - social-share-button (0.1.5) + simple_form (3.2.1) + actionpack (> 4, < 5.1) + activemodel (> 4, < 5.1) + social-share-button (0.1.10) + coffee-rails + sass-rails sprockets (3.5.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) @@ -402,13 +452,15 @@ GEM sprockets (>= 3.0.0) thor (0.19.1) thread_safe (0.3.5) - tilt (2.0.1) + tilt (2.0.2) + timers (4.1.1) + hitimes tzinfo (1.2.2) thread_safe (~> 0.1) uglifier (2.7.2) execjs (>= 0.3.0) json (>= 1.8.0) - unicorn (5.0.0) + unicorn (5.0.1) kgio (~> 2.6) rack raindrops (~> 0.7) @@ -419,7 +471,10 @@ GEM equalizer (~> 0.0, >= 0.0.9) warden (1.2.4) rack (>= 1.0) - will_paginate (3.0.7) + websocket-driver (0.6.3) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.2) + will_paginate (3.1.0) xpath (2.0.0) nokogiri (~> 1.3) @@ -427,11 +482,8 @@ PLATFORMS ruby DEPENDENCIES - actionpack-action_caching - active_model_serializers - activerecord_any_of - api_taster (= 0.6.0) - auto-space (= 0.0.4) + active_model_serializers (= 0.9.2) + auto-space better_errors binding_of_caller bundler-audit @@ -440,15 +492,14 @@ DEPENDENCIES capistrano-sidekiq capistrano-unicorn capybara (~> 2.3.0) - carrierwave (~> 0.10.0) + carrierwave carrierwave-upyun coffee-rails colorize - dalli (= 2.7.4) + dalli database_cleaner derailed - devise (~> 3.5.1) - devise-async + devise! devise-encryptable doorkeeper (~> 2.2.1) doorkeeper-i18n @@ -457,9 +508,9 @@ DEPENDENCIES elasticsearch-rails exception_notification factory_girl_rails (~> 4.5.0) - grape (= 0.7.0) + grape grape-active_model_serializers - hiredis (~> 0.6.0) + hiredis http_accept_language jasmine-rails (~> 0.10.2) jbuilder @@ -473,42 +524,44 @@ DEPENDENCIES mini_magick mongo nokogiri - omniauth (~> 1.2.2) - omniauth-github (~> 1.1.0) + omniauth + omniauth-github oneapm_rpm parallel pg - postmark (= 0.9.15) - postmark-rails (= 0.4.1) - puma (~> 2.14.0) + postmark + postmark-rails + puma rack-cors rack-mini-profiler rack-utf8_sanitizer - rails (= 4.2.5.1) - rails-i18n - rails-perftest + rails (= 5.0.0.beta1.1) + rails-i18n (~> 5.0.0.beta1) rails-settings-cached rails_autolink redcarpet (~> 3.3.4) - redis (~> 3.2.1) - redis-namespace (~> 1.5.1) - redis-objects (= 1.1.0) + redis + redis-namespace + redis-objects rouge (~> 1.8.0) - rspec-rails (~> 3.4) + rspec! + rspec-core! + rspec-expectations! + rspec-mocks! + rspec-rails! + rspec-support! rubocop - ruby-prof rucaptcha rvm-capistrano sass-rails - settingslogic (~> 2.0.9) + settingslogic sidekiq - simple_form (= 3.1.0) - sinatra - social-share-button (= 0.1.5) + simple_form + social-share-button sprockets turbolinks! uglifier - unicorn (= 5.0.0) + unicorn will_paginate BUNDLED WITH diff --git a/Gemfile1.lock b/Gemfile1.lock new file mode 100644 index 0000000000..64076cdc49 --- /dev/null +++ b/Gemfile1.lock @@ -0,0 +1,519 @@ +GIT + remote: git://github.com/rails-api/active_model_serializers.git + revision: 58ff7535b7d619028d542f49831d43504b5d89be + specs: + active_model_serializers (0.10.0.rc4) + actionpack (>= 4.0) + activemodel (>= 4.0) + railties (>= 4.0) + +GIT + remote: https://github.com/rails/turbolinks.git + revision: 37e097d24763106a7a3f06c5ec0b6242cff18ea2 + specs: + turbolinks (3.0.0) + coffee-rails + +GEM + remote: https://ruby.taobao.org/ + specs: + actionmailer (4.2.5.1) + actionpack (= 4.2.5.1) + actionview (= 4.2.5.1) + activejob (= 4.2.5.1) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 1.0, >= 1.0.5) + actionpack (4.2.5.1) + actionview (= 4.2.5.1) + activesupport (= 4.2.5.1) + rack (~> 1.6) + rack-test (~> 0.6.2) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (4.2.5.1) + activesupport (= 4.2.5.1) + builder (~> 3.1) + erubis (~> 2.7.0) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + activejob (4.2.5.1) + activesupport (= 4.2.5.1) + globalid (>= 0.3.0) + activemodel (4.2.5.1) + activesupport (= 4.2.5.1) + builder (~> 3.1) + activerecord (4.2.5.1) + activemodel (= 4.2.5.1) + activesupport (= 4.2.5.1) + arel (~> 6.0) + activerecord_any_of (1.3) + activerecord (>= 3.2.13, < 5) + activesupport (4.2.5.1) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + addressable (2.4.0) + api_taster (0.6.0) + bootstrap-sass (~> 2.1) + jquery-rails + rails (>= 3.1.0) + redcarpet + remotipart (~> 1.0) + sass-rails + arel (6.0.3) + ast (2.2.0) + auto-space (0.0.4) + activesupport (> 3.0.0) + axiom-types (0.1.1) + descendants_tracker (~> 0.0.4) + ice_nine (~> 0.11.0) + thread_safe (~> 0.3, >= 0.3.1) + bcrypt (3.1.10) + benchmark-ips (2.3.0) + better_errors (2.1.1) + coderay (>= 1.0.0) + erubis (>= 2.6.6) + rack (>= 0.9.0) + binding_of_caller (0.7.2) + debug_inspector (>= 0.0.1) + bootstrap-sass (2.3.2.2) + sass (~> 3.2) + bson (4.0.0) + builder (3.2.2) + bundler-audit (0.4.0) + bundler (~> 1.2) + thor (~> 0.18) + cancancan (1.8.4) + capistrano (2.9.0) + highline + net-scp (>= 1.0.0) + net-sftp (>= 2.0.0) + net-ssh (>= 2.0.14) + net-ssh-gateway (>= 1.1.0) + capistrano-sidekiq (0.5.4) + capistrano + sidekiq (>= 3.4) + capistrano-unicorn (0.2.0) + capistrano (< 3.0) + capybara (2.3.0) + mime-types (>= 1.16) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (~> 2.0) + carrierwave (0.10.0) + activemodel (>= 3.2.0) + activesupport (>= 3.2.0) + json (>= 1.7) + mime-types (>= 1.16) + carrierwave-upyun (0.2.1) + carrierwave (>= 0.5.7) + faraday (>= 0.8.0) + coderay (1.1.0) + coercible (1.0.0) + descendants_tracker (~> 0.0.1) + coffee-rails (4.1.1) + coffee-script (>= 2.2.0) + railties (>= 4.0.0, < 5.1.x) + coffee-script (2.4.1) + coffee-script-source + execjs + coffee-script-source (1.10.0) + colorize (0.7.7) + concurrent-ruby (1.0.0) + connection_pool (2.2.0) + dalli (2.7.4) + database_cleaner (1.5.1) + debug_inspector (0.0.2) + derailed (0.1.0) + derailed_benchmarks + derailed_benchmarks (1.1.3) + benchmark-ips (~> 2) + get_process_mem (~> 0) + heapy (~> 0) + memory_profiler (~> 0) + rack (~> 1) + rake (~> 10) + thor (~> 0.19) + descendants_tracker (0.0.4) + thread_safe (~> 0.3, >= 0.3.1) + devise (3.5.4) + bcrypt (~> 3.0) + orm_adapter (~> 0.1) + railties (>= 3.2.6, < 5) + responders + thread_safe (~> 0.1) + warden (~> 1.2.3) + devise-async (0.10.1) + devise (~> 3.2) + devise-encryptable (0.2.0) + devise (>= 2.1.0) + diff-lcs (1.2.5) + doorkeeper (2.2.2) + railties (>= 3.2) + doorkeeper-i18n (3.0.0) + dropzonejs-rails (0.7.2) + rails (> 3.1) + elasticsearch (1.0.15) + elasticsearch-api (= 1.0.15) + elasticsearch-transport (= 1.0.15) + elasticsearch-api (1.0.15) + multi_json + elasticsearch-model (0.1.8) + activesupport (> 3) + elasticsearch (> 0.4) + hashie + elasticsearch-rails (0.1.8) + elasticsearch-transport (1.0.15) + faraday + multi_json + equalizer (0.0.11) + erubis (2.7.0) + exception_notification (4.1.3) + actionmailer (~> 4.0) + activesupport (~> 4.0) + execjs (2.6.0) + factory_girl (4.5.0) + activesupport (>= 3.0.0) + factory_girl_rails (4.5.0) + factory_girl (~> 4.5.0) + railties (>= 3.0.0) + faraday (0.9.2) + multipart-post (>= 1.2, < 3) + get_process_mem (0.2.0) + globalid (0.3.6) + activesupport (>= 4.1.0) + grape (0.7.0) + activesupport + builder + hashie (>= 1.2.0) + multi_json (>= 1.3.2) + multi_xml (>= 0.5.2) + rack (>= 1.3.0) + rack-accept + rack-mount + virtus (>= 1.0.0) + grape-active_model_serializers (1.3.2) + active_model_serializers (>= 0.9.0) + grape + hashie (3.4.3) + heapy (0.1.2) + highline (1.7.8) + hiredis (0.6.1) + http_accept_language (2.0.5) + i18n (0.7.0) + ice_nine (0.11.1) + jasmine-core (2.4.1) + jasmine-rails (0.10.8) + jasmine-core (>= 1.3, < 3.0) + phantomjs (>= 1.9) + railties (>= 3.2.0) + sprockets-rails + jbuilder (2.4.0) + activesupport (>= 3.0.0, < 5.1) + multi_json (~> 1.2) + jquery-rails (4.0.5) + rails-dom-testing (~> 1.0) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) + jquery-turbolinks (2.1.0) + railties (>= 3.1.0) + turbolinks + json (1.8.3) + jwt (1.5.2) + kgio (2.10.0) + launchy (2.4.3) + addressable (~> 2.3) + letter_avatar (0.1.4) + letter_opener (1.4.1) + launchy (~> 2.2) + loofah (2.0.3) + nokogiri (>= 1.5.9) + mail (2.6.3) + mime-types (>= 1.16, < 3) + md_emoji (1.0.2) + railties (>= 3.1.0) + redcarpet (>= 2.0) + memory_profiler (0.9.6) + message_bus (1.1.1) + rack (>= 1.1.3) + redis + mime-types (2.99) + mini_magick (4.3.6) + mini_portile2 (2.0.0) + minitest (5.8.4) + mongo (2.2.1) + bson (~> 4.0) + multi_json (1.11.2) + multi_xml (0.5.5) + multipart-post (2.0.0) + net-scp (1.2.1) + net-ssh (>= 2.6.5) + net-sftp (2.1.2) + net-ssh (>= 2.6.5) + net-ssh (3.0.1) + net-ssh-gateway (1.2.0) + net-ssh (>= 2.6.5) + nokogiri (1.6.7.2) + mini_portile2 (~> 2.0.0.rc2) + oauth2 (1.0.0) + faraday (>= 0.8, < 0.10) + jwt (~> 1.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (~> 1.2) + omniauth (1.2.2) + hashie (>= 1.2, < 4) + rack (~> 1.0) + omniauth-github (1.1.2) + omniauth (~> 1.0) + omniauth-oauth2 (~> 1.1) + omniauth-oauth2 (1.4.0) + oauth2 (~> 1.0) + omniauth (~> 1.2) + oneapm_rpm (1.3.3) + orm_adapter (0.5.0) + parallel (1.6.1) + parser (2.3.0.1) + ast (~> 2.2) + pg (0.18.4) + phantomjs (1.9.8.0) + posix-spawn (0.3.11) + postmark (0.9.15) + json + rake + postmark-rails (0.4.1) + actionmailer + postmark (>= 0.9.0) + rake + powerpack (0.1.1) + puma (2.14.0) + rack (1.6.4) + rack-accept (0.4.5) + rack (>= 0.4) + rack-cors (0.4.0) + rack-mini-profiler (0.9.8) + rack (>= 1.1.3) + rack-mount (0.8.3) + rack (>= 1.0.0) + rack-protection (1.5.3) + rack + rack-test (0.6.3) + rack (>= 1.0) + rack-utf8_sanitizer (1.3.2) + rack (>= 1.0, < 3.0) + rails (4.2.5.1) + actionmailer (= 4.2.5.1) + actionpack (= 4.2.5.1) + actionview (= 4.2.5.1) + activejob (= 4.2.5.1) + activemodel (= 4.2.5.1) + activerecord (= 4.2.5.1) + activesupport (= 4.2.5.1) + bundler (>= 1.3.0, < 2.0) + railties (= 4.2.5.1) + sprockets-rails + rails-deprecated_sanitizer (1.0.3) + activesupport (>= 4.2.0.alpha) + rails-dom-testing (1.0.7) + activesupport (>= 4.2.0.beta, < 5.0) + nokogiri (~> 1.6.0) + rails-deprecated_sanitizer (>= 1.0.1) + rails-html-sanitizer (1.0.3) + loofah (~> 2.0) + rails-i18n (4.0.8) + i18n (~> 0.7) + railties (~> 4.0) + rails-perftest (0.0.6) + rails-settings-cached (0.5.3) + rails (>= 4.2.0) + rails_autolink (1.1.6) + rails (> 3.1) + railties (4.2.5.1) + actionpack (= 4.2.5.1) + activesupport (= 4.2.5.1) + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + rainbow (2.0.0) + raindrops (0.15.0) + rake (10.5.0) + redcarpet (3.3.4) + redis (3.2.2) + redis-namespace (1.5.2) + redis (~> 3.0, >= 3.0.4) + redis-objects (1.1.0) + redis (>= 3.0.2) + remotipart (1.2.1) + responders (2.1.1) + railties (>= 4.2.0, < 5.1) + rouge (1.8.0) + rspec-core (3.4.1) + rspec-support (~> 3.4.0) + rspec-expectations (3.4.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.4.0) + rspec-mocks (3.4.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.4.0) + rspec-rails (3.4.0) + actionpack (>= 3.0, < 4.3) + activesupport (>= 3.0, < 4.3) + railties (>= 3.0, < 4.3) + rspec-core (~> 3.4.0) + rspec-expectations (~> 3.4.0) + rspec-mocks (~> 3.4.0) + rspec-support (~> 3.4.0) + rspec-support (3.4.1) + rubocop (0.36.0) + parser (>= 2.3.0.0, < 3.0) + powerpack (~> 0.1) + rainbow (>= 1.99.1, < 3.0) + ruby-progressbar (~> 1.7) + ruby-prof (0.15.9) + ruby-progressbar (1.7.5) + rucaptcha (0.3.2) + posix-spawn (>= 0.3.0) + rvm-capistrano (1.4.1) + capistrano (>= 2.0.0) + sass (3.4.20) + sass-rails (5.0.4) + railties (>= 4.0.0, < 5.0) + sass (~> 3.1) + sprockets (>= 2.8, < 4.0) + sprockets-rails (>= 2.0, < 4.0) + tilt (>= 1.1, < 3) + settingslogic (2.0.9) + sidekiq (4.0.1) + concurrent-ruby (~> 1.0) + connection_pool (~> 2.2, >= 2.2.0) + json (~> 1.0) + redis (~> 3.2, >= 3.2.1) + simple_form (3.1.0) + actionpack (~> 4.0) + activemodel (~> 4.0) + sinatra (1.4.6) + rack (~> 1.4) + rack-protection (~> 1.4) + tilt (>= 1.3, < 3) + social-share-button (0.1.5) + sprockets (3.5.2) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.0.0) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + thor (0.19.1) + thread_safe (0.3.5) + tilt (2.0.1) + tzinfo (1.2.2) + thread_safe (~> 0.1) + uglifier (2.7.2) + execjs (>= 0.3.0) + json (>= 1.8.0) + unicorn (5.0.0) + kgio (~> 2.6) + rack + raindrops (~> 0.7) + virtus (1.0.5) + axiom-types (~> 0.1) + coercible (~> 1.0) + descendants_tracker (~> 0.0, >= 0.0.3) + equalizer (~> 0.0, >= 0.0.9) + warden (1.2.4) + rack (>= 1.0) + will_paginate (3.0.7) + xpath (2.0.0) + nokogiri (~> 1.3) + +PLATFORMS + ruby + +DEPENDENCIES + active_model_serializers! + activerecord_any_of + api_taster (= 0.6.0) + auto-space (= 0.0.4) + better_errors + binding_of_caller + bundler-audit + cancancan (~> 1.8.4) + capistrano (= 2.9.0) + capistrano-sidekiq + capistrano-unicorn + capybara (~> 2.3.0) + carrierwave (~> 0.10.0) + carrierwave-upyun + coffee-rails + colorize + dalli (= 2.7.4) + database_cleaner + derailed + devise (~> 3.5.1) + devise-async + devise-encryptable + doorkeeper (~> 2.2.1) + doorkeeper-i18n + dropzonejs-rails + elasticsearch-model + elasticsearch-rails + exception_notification + factory_girl_rails (~> 4.5.0) + grape (= 0.7.0) + grape-active_model_serializers + hiredis (~> 0.6.0) + http_accept_language + jasmine-rails (~> 0.10.2) + jbuilder + jquery-rails + jquery-turbolinks + kgio + letter_avatar + letter_opener + md_emoji + message_bus + mini_magick + mongo + nokogiri + omniauth (~> 1.2.2) + omniauth-github (~> 1.1.0) + oneapm_rpm + parallel + pg + postmark (= 0.9.15) + postmark-rails (= 0.4.1) + puma + rack-cors + rack-mini-profiler + rack-utf8_sanitizer + rails (= 4.2.5.1) + rails-i18n + rails-perftest + rails-settings-cached + rails_autolink + redcarpet (~> 3.3.4) + redis (~> 3.2.1) + redis-namespace (~> 1.5.1) + redis-objects (= 1.1.0) + rouge (~> 1.8.0) + rspec-rails + rubocop + ruby-prof + rucaptcha + rvm-capistrano + sass-rails + settingslogic (~> 2.0.9) + sidekiq + simple_form (= 3.1.0) + sinatra + social-share-button (= 0.1.5) + sprockets + turbolinks! + uglifier + unicorn (= 5.0.0) + will_paginate + +BUNDLED WITH + 1.11.2 diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index cfad963455..fb4843ab4a 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -1,7 +1,6 @@ class TopicsController < ApplicationController load_and_authorize_resource only: [:new, :edit, :create, :update, :destroy, :favorite, :unfavorite, :follow, :unfollow, :suggest, :unsuggest, :ban] - caches_action :feed, :node_feed, expires_in: 1.hours def index @threads = [] diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb new file mode 100644 index 0000000000..a009ace51c --- /dev/null +++ b/app/jobs/application_job.rb @@ -0,0 +1,2 @@ +class ApplicationJob < ActiveJob::Base +end diff --git a/app/jobs/github_repo_fetcher_job.rb b/app/jobs/github_repo_fetcher_job.rb index aba6ea0c33..60e7a333ba 100644 --- a/app/jobs/github_repo_fetcher_job.rb +++ b/app/jobs/github_repo_fetcher_job.rb @@ -1,4 +1,4 @@ -class GithubRepoFetcherJob < ActiveJob::Base +class GithubRepoFetcherJob < ApplicationJob queue_as :http_request def perform(user_id) diff --git a/app/jobs/notify_reply_job.rb b/app/jobs/notify_reply_job.rb index 836b7d6ff9..1603fb4400 100644 --- a/app/jobs/notify_reply_job.rb +++ b/app/jobs/notify_reply_job.rb @@ -1,4 +1,4 @@ -class NotifyReplyJob < ActiveJob::Base +class NotifyReplyJob < ApplicationJob queue_as :notifications def perform(reply_id) diff --git a/app/jobs/notify_topic_job.rb b/app/jobs/notify_topic_job.rb index 1794f5bf89..ec950e73c8 100644 --- a/app/jobs/notify_topic_job.rb +++ b/app/jobs/notify_topic_job.rb @@ -1,4 +1,4 @@ -class NotifyTopicJob < ActiveJob::Base +class NotifyTopicJob < ApplicationJob queue_as :notifications def perform(topic_id) diff --git a/app/jobs/search_indexer.rb b/app/jobs/search_indexer.rb index 9b3db79f47..e3b0685f07 100644 --- a/app/jobs/search_indexer.rb +++ b/app/jobs/search_indexer.rb @@ -1,4 +1,4 @@ -class SearchIndexer < ActiveJob::Base +class SearchIndexer < ApplicationJob queue_as :search_indexer def perform(operation, type, id) diff --git a/app/models/application_record.rb b/app/models/application_record.rb new file mode 100644 index 0000000000..10a4cba84d --- /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/authorization.rb b/app/models/authorization.rb index 0ebc921324..938e89bdb2 100644 --- a/app/models/authorization.rb +++ b/app/models/authorization.rb @@ -1,4 +1,4 @@ -class Authorization < ActiveRecord::Base +class Authorization < ApplicationRecord belongs_to :user validates :uid, :provider, presence: true validates :uid, uniqueness: { scope: :provider } diff --git a/app/models/comment.rb b/app/models/comment.rb index 56cf1cda7e..b8a7372004 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,4 +1,4 @@ -class Comment < ActiveRecord::Base +class Comment < ApplicationRecord include BaseModel include MarkdownBody diff --git a/app/models/concerns/base_model.rb b/app/models/concerns/base_model.rb index f70c669cde..54ba817410 100644 --- a/app/models/concerns/base_model.rb +++ b/app/models/concerns/base_model.rb @@ -7,27 +7,27 @@ module BaseModel scope :by_week, -> { where("created_at > ?", 7.days.ago.utc) } delegate :url_helpers, to: 'Rails.application.routes' + end - # FIXME: 需要原子化操作 - def push(hash) - hash.each_key do |key| - self.send("#{key}_will_change!") - old_val = self[key] || [] - old_val << hash[key].to_i - old_val.uniq! - update_attributes(key => old_val) - end + # FIXME: 需要原子化操作 + def push(hash) + hash.each_key do |key| + self.send("#{key}_will_change!") + old_val = self[key] || [] + old_val << hash[key].to_i + old_val.uniq! + update_attributes(key => old_val) end + end - # FIXME: 需要原子化操作 - def pull(hash) - hash.each_key do |key| - self.send("#{key}_will_change!") - old_val = self[key] - return true if old_val.blank? - old_val.delete(hash[key].to_i) - update_attributes(key => old_val) - end + # FIXME: 需要原子化操作 + def pull(hash) + hash.each_key do |key| + self.send("#{key}_will_change!") + old_val = self[key] + return true if old_val.blank? + old_val.delete(hash[key].to_i) + update_attributes(key => old_val) end end end diff --git a/app/models/exception_log.rb b/app/models/exception_log.rb index f3dd531994..a260e68b12 100644 --- a/app/models/exception_log.rb +++ b/app/models/exception_log.rb @@ -1,2 +1,2 @@ -class ExceptionLog < ActiveRecord::Base +class ExceptionLog < ApplicationRecord end diff --git a/app/models/location.rb b/app/models/location.rb index 754195fb3a..900be1c48b 100644 --- a/app/models/location.rb +++ b/app/models/location.rb @@ -1,4 +1,4 @@ -class Location < ActiveRecord::Base +class Location < ApplicationRecord has_many :users scope :hot, -> { order(users_count: :desc) } diff --git a/app/models/node.rb b/app/models/node.rb index 6fc16cb1c8..6cbede7aa4 100644 --- a/app/models/node.rb +++ b/app/models/node.rb @@ -1,4 +1,4 @@ -class Node < ActiveRecord::Base +class Node < ApplicationRecord delegate :name, to: :section, prefix: true, allow_nil: true diff --git a/app/models/note.rb b/app/models/note.rb index 01b4c5ec49..b87955aaac 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -1,5 +1,5 @@ # 记事本 -class Note < ActiveRecord::Base +class Note < ApplicationRecord include BaseModel include Redis::Objects diff --git a/app/models/notification/base.rb b/app/models/notification/base.rb index 1ca9dca392..50bc77dd5f 100644 --- a/app/models/notification/base.rb +++ b/app/models/notification/base.rb @@ -1,5 +1,5 @@ module Notification - class Base < ActiveRecord::Base + class Base < ApplicationRecord include BaseModel self.table_name = 'notifications' diff --git a/app/models/page.rb b/app/models/page.rb index 7641d116e6..d81e3547d1 100644 --- a/app/models/page.rb +++ b/app/models/page.rb @@ -1,7 +1,7 @@ # 单页的文档页面 # 采用 Markdown 编写 require 'redcarpet' -class Page < ActiveRecord::Base +class Page < ApplicationRecord include BaseModel include MarkdownBody include Elasticsearch::Model diff --git a/app/models/page_version.rb b/app/models/page_version.rb index 832e00dba1..04a54c3fa5 100644 --- a/app/models/page_version.rb +++ b/app/models/page_version.rb @@ -1,4 +1,4 @@ -class PageVersion < ActiveRecord::Base +class PageVersion < ApplicationRecord belongs_to :user belongs_to :page end diff --git a/app/models/photo.rb b/app/models/photo.rb index 10e6241328..27759ad9b5 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -1,4 +1,4 @@ -class Photo < ActiveRecord::Base +class Photo < ApplicationRecord include BaseModel belongs_to :user diff --git a/app/models/reply.rb b/app/models/reply.rb index 4d2fef1309..53b02d10e0 100644 --- a/app/models/reply.rb +++ b/app/models/reply.rb @@ -1,5 +1,5 @@ require 'digest/md5' -class Reply < ActiveRecord::Base +class Reply < ApplicationRecord include BaseModel include SoftDelete include MarkdownBody diff --git a/app/models/section.rb b/app/models/section.rb index a53da6f432..bb5bf53ad0 100644 --- a/app/models/section.rb +++ b/app/models/section.rb @@ -1,4 +1,4 @@ -class Section < ActiveRecord::Base +class Section < ApplicationRecord has_many :nodes, dependent: :destroy diff --git a/app/models/site.rb b/app/models/site.rb index 56f6f6faba..36b824c470 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -1,4 +1,4 @@ -class Site < ActiveRecord::Base +class Site < ApplicationRecord include BaseModel include SoftDelete diff --git a/app/models/site_node.rb b/app/models/site_node.rb index 52c7c24070..6eadcd3d48 100644 --- a/app/models/site_node.rb +++ b/app/models/site_node.rb @@ -1,4 +1,4 @@ -class SiteNode < ActiveRecord::Base +class SiteNode < ApplicationRecord has_many :sites diff --git a/app/models/topic.rb b/app/models/topic.rb index df4bb43dce..fd07a5a92f 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -7,7 +7,7 @@ [')', ')'] ] -class Topic < ActiveRecord::Base +class Topic < ApplicationRecord include Redis::Objects include BaseModel include Likeable diff --git a/app/models/user.rb b/app/models/user.rb index 9049bd19bf..c2b666b755 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -2,7 +2,7 @@ require 'digest/md5' require 'open-uri' -class User < ActiveRecord::Base +class User < ApplicationRecord include Redis::Objects include BaseModel extend OmniauthCallbacks @@ -12,7 +12,7 @@ class User < ActiveRecord::Base ALLOW_LOGIN_CHARS_REGEXP = /\A\w+\z/ devise :database_authenticatable, :registerable, :recoverable, - :rememberable, :trackable, :validatable, :omniauthable, :async + :rememberable, :trackable, :validatable, :omniauthable mount_uploader :avatar, AvatarUploader @@ -246,9 +246,14 @@ def read_topic(topic, opts = {}) opts[:replies_ids] ||= topic.replies.pluck(:id) - notifications.unread.where.any_of({ mentionable_type: 'Topic', mentionable_id: topic.id }, - { mentionable_type: 'Reply', mentionable_id: opts[:replies_ids] }, - reply_id: opts[:replies_ids]).update_all(read: true) + any_sql = " + (mentionable_type = 'Topic' AND mentionable_id = ?) or + (mentionable_type = 'Reply' AND mentionable_id in (?)) or + (reply_id in (?)) + " + notifications.unread + .where(any_sql, topic.id, opts[:replies_ids], opts[:replies_ids]) + .update_all(read: true) # 处理 last_reply_id 是空的情况 last_reply_id = topic.last_reply_id || -1 diff --git a/bin/provision.sh b/bin/provision.sh old mode 100644 new mode 100755 diff --git a/bin/setup b/bin/setup index f25e1061f3..c0d5d9f64f 100755 --- a/bin/setup +++ b/bin/setup @@ -62,7 +62,7 @@ end Dir.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_section 'Checking Package Dependencies...' do pkg_exist = true diff --git a/bin/update b/bin/update new file mode 100755 index 0000000000..985192370d --- /dev/null +++ b/bin/update @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a way to update your development environment automatically. + # Add necessary update steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system 'bundle check' or system! 'bundle install' + + puts "\n== Updating database ==" + system! 'bin/rails db:migrate' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/config.ru b/config.ru index 1dcf7c6135..97af810d95 100644 --- a/config.ru +++ b/config.ru @@ -2,9 +2,11 @@ require ::File.expand_path('../config/environment', __FILE__) -# NewRelic::Agent.manual_start +# Action Cable uses EventMachine which requires that all classes are loaded in advance +Rails.application.eager_load! +# require 'action_cable/process/logging' -run RubyChina::Application +run Rails.application memory_usage = (`ps -o rss= -p #{$PID}`.to_i / 1024.00).round(2) puts "=> Memory usage: #{memory_usage} MB" diff --git a/config/application.rb b/config/application.rb index e54e401c76..01e38cbc10 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,21 +1,19 @@ require File.expand_path('../boot', __FILE__) -require "active_model/railtie" -require "active_job/railtie" -require "active_record/railtie" -require 'action_controller/railtie' -require 'action_mailer/railtie' -require "action_view/railtie" -require 'rails/test_unit/railtie' -require 'sprockets/railtie' - -if defined?(Bundler) - Bundler.require(*Rails.groups(assets: %w(production development test))) -end +require 'rails/all' + +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(*Rails.groups) module RubyChina class Application < Rails::Application - # Custom directories with classes and modules you want to be autoloadable. + # 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. + + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. + # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. config.time_zone = 'Beijing' # Ensure App config files exist. @@ -31,10 +29,12 @@ class Application < Rails::Application config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] config.i18n.default_locale = 'zh-CN' config.i18n.available_locales = ['zh-CN', 'en', 'zh-TW'] + + # Do not swallow errors in after_commit/after_rollback callbacks. config.i18n.fallbacks = true config.autoload_paths.push(*%W(#{config.root}/lib)) - config.eager_load_paths += %W( #{config.root}/lib/exception_notifier ) + config.eager_load_paths.push(*%W(#{config.root}/lib/exception_notifier)) config.generators do |g| g.test_framework :rspec @@ -51,18 +51,8 @@ class Application < Rails::Application Doorkeeper::AuthorizedApplicationsController.layout 'simple' end - config.middleware.use Rack::Cors do - allow do - origins '*' - resource '/api/*', headers: :any, methods: [:get, :post, :put, :delete, :destroy] - resource '/oauth/*', headers: :any, methods: [:get, :post, :put, :delete, :destroy] - end - end - config.cache_store = [:dalli_store, '127.0.0.1', { namespace: 'rb-1', compress: true }] - config.middleware.insert 0, Rack::UTF8Sanitizer - config.active_job.queue_adapter = :sidekiq config.active_record.raise_in_transactional_callbacks = true diff --git a/config/config.yml.default b/config/config.yml.default index 3d51beb6f7..9b5b853518 100644 --- a/config/config.yml.default +++ b/config/config.yml.default @@ -1,7 +1,7 @@ defaults: &defaults app_name: "Ruby China" foot_html: "© Ruby China." - domain: "127.0.0.1:3000" + domain: "localhost:3000" https: false admin_emails: - "admin@admin.com" diff --git a/config/environments/development.rb b/config/environments/development.rb index fecbb41263..b22ceceaea 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,39 +1,57 @@ Rails.application.configure do - # Settings specified here will take precedence over those in config/environment.rb + # Settings specified here will take precedence over those in config/application.rb. # In the development environment your application's code is reloaded on - # every request. This slows down response time but is perfect for development - # since you don't have to restart the webserver when you make code changes. + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. config.cache_classes = false + # Do not eager load code on boot. config.eager_load = false - # Show full error reports and disable caching - config.consider_all_requests_local = true + # Show full error reports. + config.consider_all_requests_local = true config.action_controller.perform_caching = true - # Don't care if the mailer can't send + # Enable/disable caching. By default caching is disabled. + if Rails.root.join('tmp/caching-dev.txt').exist? + config.action_controller.perform_caching = true + config.cache_store = :memory_store + config.public_file_server.headers = { + 'Cache-Control' => 'public, max-age=172800' + } + else + config.action_controller.perform_caching = false + config.cache_store = :null_store + end + + # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false - # config.action_mailer.delivery_method = :letter_opener - config.action_mailer.default_url_options = { host: Setting.domain } - config.action_mailer.delivery_method = :letter_opener - # Print deprecation notices to the Rails logger + # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log - config.assets.debug = false + # Raise an error on page load if there are pending migrations. + config.active_record.migration_error = :page_load + + # Debug mode disables concatenation and preprocessing of assets. + # This option may cause significant delays in view rendering with a large + # number of complex assets. + config.assets.debug = true # Asset digests allow you to set far-future HTTP expiration dates on all assets, # yet still be able to expire them through the digest params. - config.assets.digest = false + config.assets.digest = true # Adds additional error checking when serving assets at runtime. # Checks for improperly declared sprockets dependencies. # Raises helpful error messages. - config.assets.raise_runtime_errors = false - - config.active_job.queue_adapter = :inline + config.assets.raise_runtime_errors = true # Raises error for missing translations # config.action_view.raise_on_missing_translations = true + + # Use an evented file watcher to asynchronously detect changes in source code, + # routes, locales, etc. This feature depends on the listen gem. + # config.file_watcher = ActiveSupport::EventedFileUpdateChecker end diff --git a/config/environments/production.rb b/config/environments/production.rb index a9b3e5f8d9..59bed8baa3 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,5 +1,5 @@ Rails.application.configure do - # Settings specified here will take precedence over those in config/environment.rb + # Settings specified here will take precedence over those in config/application.rb. # Code is not reloaded between requests. config.cache_classes = true @@ -10,65 +10,71 @@ # Rake tasks automatically ignore this option for performance. config.eager_load = true - # Full error reports are disabled and caching is turned on + # Full error reports are disabled and caching is turned on. config.consider_all_requests_local = false config.action_controller.perform_caching = true - # Enable Rack::Cache to put a simple HTTP cache in front of your application - # Add `rack-cache` to your Gemfile before enabling this. - # For large-scale production use, consider using a caching reverse proxy like - # NGINX, varnish or squid. - # config.action_dispatch.rack_cache = true + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? - # Disable Rails's static asset server (Apache or NGINX will already do this). - config.serve_static_files = false + # Compress JavaScripts and CSS. + config.assets.js_compressor = :uglifier + config.assets.css_compressor = :sass - # Compress JavaScripts and CSS - config.assets.compress = true - - # Don't fallback to assets pipeline if a precompiled asset is missed + # Do not fallback to assets pipeline if a precompiled asset is missed. config.assets.compile = false - # Generate digests for assets URLs + # Asset digests allow you to set far-future HTTP expiration dates on all assets, + # yet still be able to expire them through the digest params. config.assets.digest = true - config.assets.js_compressor = :uglifier - config.assets.css_compressor = :scss + # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + config.action_controller.asset_host = Setting.upload_url - # Specifies the header that your server uses for sending files - # config.action_dispatch.x_sendfile_header = "X-Sendfile" + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache + config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX - # For nginx: - config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' + # Action Cable endpoint configuration + # config.action_cable.url = 'wss://example.com/cable' + # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. config.force_ssl = true - # Decrease the log volume. + # Use the lowest log level to ensure availability of diagnostic information + # when problems arise. config.log_level = :info + # Prepend all log lines with the following tags. + # config.log_tags = [ :subdomain, :request_id ] + # Use a different logger for distributed setups. - # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) + # require 'syslog/logger' + # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') - # Enable serving of images, stylesheets, and javascripts from an asset server - config.action_controller.asset_host = Setting.upload_url + # Use a different cache store in production. + # config.cache_store = :mem_cache_store - # Disable delivery errors, bad email addresses will be ignored + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. # config.action_mailer.raise_delivery_errors = false config.action_mailer.default_url_options = { host: Setting.domain, protocol: Setting.protocol } config.action_mailer.delivery_method = :postmark config.action_mailer.postmark_settings = { api_key: Setting.email_password } - # Enable threaded mode - # config.threadsafe! - # Enable locale fallbacks for I18n (makes lookups for any locale fall back to - # the I18n.default_locale when a translation can not be found) + # the I18n.default_locale when a translation cannot be found). config.i18n.fallbacks = true - # Send deprecation notices to registered listeners + # Send deprecation notices to registered listeners. config.active_support.deprecation = :notify + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new + # Do not dump schema after migrations. - # config.active_record.dump_schema_after_migration = false + config.active_record.dump_schema_after_migration = false end diff --git a/config/environments/test.rb b/config/environments/test.rb index 5356a366ff..091cd87cfc 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=3600' + } # Show full error reports and disable caching. config.consider_all_requests_local = true @@ -31,7 +33,7 @@ # ActionMailer::Base.deliveries array. config.action_mailer.delivery_method = :test - # Randomize the order test cases are executed + # Randomize the order test cases are executed. config.active_support.test_order = :random # Print deprecation notices to the stderr. diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb new file mode 100644 index 0000000000..51639b67a0 --- /dev/null +++ b/config/initializers/application_controller_renderer.rb @@ -0,0 +1,6 @@ +# Be sure to restart your server when you modify this file. + +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 81947846b6..f83a47975e 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -1,7 +1,11 @@ # Be sure to restart your server when you modify this file. + # Version of your assets, change this if you want to expire all your assets. Rails.application.config.assets.version = '1.0' +# Add additional assets to the asset load path +# Rails.application.config.assets.paths << Emoji.images_path + # Precompile additional assets. # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. Rails.application.config.assets.precompile += %w(application.css app.js topics.css topics.js front.css cpanel.css diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb index 8758771552..93329258f7 100644 --- a/config/initializers/cookies_serializer.rb +++ b/config/initializers/cookies_serializer.rb @@ -1,2 +1,4 @@ # Be sure to restart your server when you modify this file. -Rails.application.config.action_dispatch.cookies_serializer = :hybrid + +# This is a new Rails 5.0 default, so introduced as a config to ensure apps made with earlier versions of Rails aren't affected when upgrading. +Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/config/initializers/cors.rb b/config/initializers/cors.rb new file mode 100644 index 0000000000..34ffdcfa0c --- /dev/null +++ b/config/initializers/cors.rb @@ -0,0 +1,16 @@ +# Be sure to restart your server when you modify this file. + +# Avoid CORS issues when API is called from the frontend app. +# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests. + +# Read more: https://github.com/cyu/rack-cors + +Rails.application.config.middleware.insert_before 0, Rack::Cors do + allow do + origins '*' + resource '/api/*', headers: :any, methods: [:get, :post, :put, :delete, :destroy] + resource '/oauth/*', headers: :any, methods: [:get, :post, :put, :delete, :destroy] + end +end + +Rails.application.config.middleware.insert_before 0, Rack::UTF8Sanitizer diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index ca6ede3854..510ce01518 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -191,5 +191,3 @@ # manager.default_strategies(:scope => :user).unshift :twitter_oauth # end end - -Devise::Async.backend = :sidekiq diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index 9e8b0131f8..ac033bf9dc 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -1,10 +1,16 @@ # Be sure to restart your server when you modify this file. -# Add new inflection rules using the following format -# (all these examples are active by default): -# ActiveSupport::Inflector.inflections do |inflect| +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| # inflect.plural /^(ox)$/i, '\1en' # inflect.singular /^(ox)en/i, '\1' # inflect.irregular 'person', 'people' # inflect.uncountable %w( fish sheep ) # end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym 'RESTful' +# end diff --git a/config/initializers/request_forgery_protection.rb b/config/initializers/request_forgery_protection.rb new file mode 100644 index 0000000000..3eab78a885 --- /dev/null +++ b/config/initializers/request_forgery_protection.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Enable origin-checking CSRF mitigation. +Rails.application.config.action_controller.forgery_protection_origin_check = true diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index 0f699be70b..c5e70c7dd8 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -1,8 +1,3 @@ # Be sure to restart your server when you modify this file. Rails.application.config.session_store :cookie_store, key: '_homeland_session' - -# Use the database for sessions instead of the cookie-based default, -# which shouldn't be used to store highly confidential information -# (create the session table with "rake db:sessions:create") -# RubyChina::Application.config.session_store :active_record_store diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index 33725e95fd..cf733efd11 100644 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -5,7 +5,7 @@ # 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. diff --git a/config/locales/en.yml b/config/locales/en.yml index e865dd1673..23d9a96b57 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,7 +1,25 @@ -# Sample localization file for English. Add more files in this directory for other locales. -# See http://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. +# +# To learn more, please read the Rails Internationalization guide +# available at http://guides.rubyonrails.org/i18n.html. -"en": +en: omniauth: github: GitHub twitter: Twitter @@ -38,13 +56,13 @@ node_id: "Node" body: "Content" reply: - body: "Reply Content" + body: "Reply Content" post: title: "Title" body: "Content" tag_list: "Tags" source: "Source" - source_url: "Source Url" + source_url: "Source Url" page: slug: Slug title: "Title" @@ -61,7 +79,7 @@ body: Details errors: models: - user: "User" + user: "User" messages: inclusion: "Inclusion" exclusion: "Exclusion" diff --git a/config/redis/cable.yml b/config/redis/cable.yml new file mode 100644 index 0000000000..0176be24f9 --- /dev/null +++ b/config/redis/cable.yml @@ -0,0 +1,9 @@ +# Action Cable uses Redis to administer connections, channels, and sending/receiving messages over the WebSocket. +production: + url: redis://localhost:6379/1 + +development: + url: redis://localhost:6379/2 + +test: + url: redis://localhost:6379/3 diff --git a/config/routes.rb b/config/routes.rb index 60daa292ce..ebfddaee7e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,8 @@ Rails.application.routes.draw do + # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html + + # Serve websocket cable requests in-process + # mount ActionCable.server => '/cable' mount RuCaptcha::Engine => "/rucaptcha" use_doorkeeper do @@ -119,10 +123,10 @@ mount API::Dispatch => '/api' - require 'sidekiq/web' - authenticate :user, ->(u) { u.admin? } do - mount Sidekiq::Web => '/sidekiq' - end + # require 'sidekiq/web' + # authenticate :user, ->(u) { u.admin? } do + # mount Sidekiq::Web => '/sidekiq' + # end mount JasmineRails::Engine => '/specs' if defined?(JasmineRails) diff --git a/db/migrate/20160126061903_create_settings.rb b/db/migrate/20160126061903_create_settings.rb index d77eefd748..11e9bd169f 100644 --- a/db/migrate/20160126061903_create_settings.rb +++ b/db/migrate/20160126061903_create_settings.rb @@ -1,4 +1,4 @@ -class OldSiteConfig < ActiveRecord::Base +class OldSiteConfig < ApplicationRecord self.table_name = 'site_configs' end diff --git a/lib/api/v3/root.rb b/lib/api/v3/root.rb index 6b802f1ab3..b71b5a83f9 100644 --- a/lib/api/v3/root.rb +++ b/lib/api/v3/root.rb @@ -26,7 +26,7 @@ class Root < Grape::API else Rails.logger.error "Api V3 Error: #{e}\n#{e.backtrace.join("\n")}" end - Rack::Response.new([{ error: 'API 接口异常' }.to_json], 500, {}).finish + Rack::Response.new([{ error: "API 接口异常" }.to_json], 500, {}).finish end end diff --git a/spec/models/concerns/base_model_spec.rb b/spec/models/concerns/base_model_spec.rb index e6440ae97f..e79eee7c50 100644 --- a/spec/models/concerns/base_model_spec.rb +++ b/spec/models/concerns/base_model_spec.rb @@ -6,7 +6,7 @@ t.timestamps null: false end - class Monkey < ActiveRecord::Base + class Monkey < ApplicationRecord include BaseModel end diff --git a/spec/models/concerns/mentionable_spec.rb b/spec/models/concerns/mentionable_spec.rb index ebcbae1ad9..8f87fabbe6 100644 --- a/spec/models/concerns/mentionable_spec.rb +++ b/spec/models/concerns/mentionable_spec.rb @@ -7,7 +7,7 @@ t.timestamps null: false end -class TestDocument < ActiveRecord::Base +class TestDocument < ApplicationRecord include Mentionable belongs_to :user diff --git a/spec/models/concerns/soft_delete_spec.rb b/spec/models/concerns/soft_delete_spec.rb index 2fb123d86e..50db23a0f1 100644 --- a/spec/models/concerns/soft_delete_spec.rb +++ b/spec/models/concerns/soft_delete_spec.rb @@ -8,7 +8,7 @@ t.timestamps null: false end - class WalkingDead < ActiveRecord::Base + class WalkingDead < ApplicationRecord include BaseModel include SoftDelete diff --git a/spec/support/api_v3_support.rb b/spec/support/api_v3_support.rb index 7798dfd7fb..5b8a0b320c 100644 --- a/spec/support/api_v3_support.rb +++ b/spec/support/api_v3_support.rb @@ -30,7 +30,7 @@ def #{method}(path, parameters = nil, headers = nil) # override empty params and headers with default parameters = combine_parameters(parameters, default_parameters) headers = combine_parameters(headers, default_headers) - super(path, parameters, headers) + super(path, params: parameters, headers: headers) end EOV end From bf2ac0ed8c30cc52e61c3d2d4c888fce0e3c7c08 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Thu, 28 Jan 2016 21:50:07 +0800 Subject: [PATCH 02/19] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20validation=5Ferrors?= =?UTF-8?q?=20=E7=9A=84=E8=BE=93=E5=87=BA=E7=BB=93=E6=9E=84;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/api/v3/root.rb | 2 +- spec/api/root_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/api/v3/root.rb b/lib/api/v3/root.rb index b71b5a83f9..d4c0bb0016 100644 --- a/lib/api/v3/root.rb +++ b/lib/api/v3/root.rb @@ -17,7 +17,7 @@ class Root < Grape::API when Grape::Exceptions::ValidationErrors Rack::Response.new([{ error: '参数不符合要求,请检查参数是否按照 API 要求传输。', - validation_errors: e.errors + validation_errors: e.full_messages }.to_json], 400, {}).finish else # ExceptionNotifier.notify_exception(e) # Uncommit it when ExceptionNotification is available diff --git a/spec/api/root_spec.rb b/spec/api/root_spec.rb index 47fd9d17ca..c7d2a7abfb 100644 --- a/spec/api/root_spec.rb +++ b/spec/api/root_spec.rb @@ -40,8 +40,8 @@ get '/api/v3/hello.json', limit: 2000 expect(response.status).to eq 400 expect(json['validation_errors'].size).to eq 1 - expect(json['validation_errors']).to include(*%w(limit)) - expect(json['validation_errors']['limit'][0]).to include('valid value') + # puts json.inspect + expect(json['validation_errors']).to include(*['limit does not have a valid value']) end end end From 67ff39d3ca9680d17a0679e31250794b92266294 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Thu, 28 Jan 2016 22:26:19 +0800 Subject: [PATCH 03/19] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=B5=8B=E8=AF=95;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile | 6 +++-- Gemfile.lock | 19 +++++++++++---- app/controllers/likes_controller.rb | 8 +++---- app/controllers/notes_controller.rb | 2 +- app/controllers/pages_controller.rb | 2 +- app/controllers/topics_controller.rb | 8 +++---- app/controllers/users_controller.rb | 2 +- config/routes.rb | 2 +- .../cpanel/comments_controller_spec.rb | 17 +++++++------ spec/controllers/likes_controller_spec.rb | 20 ++++++++-------- spec/controllers/notes_controller_spec.rb | 4 ++-- .../notifications_controller_spec.rb | 2 +- spec/controllers/pages_controller_spec.rb | 22 ++++++++--------- spec/controllers/replies_controller_spec.rb | 14 +++++------ spec/controllers/sites_controller_spec.rb | 6 ++--- spec/controllers/topics_controller_spec.rb | 24 +++++++++---------- spec/controllers/users_controller_spec.rb | 22 ++++++++--------- 17 files changed, 97 insertions(+), 83 deletions(-) diff --git a/Gemfile b/Gemfile index 32203fa32b..9800e1506d 100644 --- a/Gemfile +++ b/Gemfile @@ -23,7 +23,7 @@ gem 'rails_autolink' gem 'md_emoji' gem 'exception_notification' -gem 'doorkeeper', '~> 2.2.1' +gem 'doorkeeper', github: 'doorkeeper-gem/doorkeeper' gem 'doorkeeper-i18n' # gem 'rails-perftest' @@ -142,9 +142,11 @@ group :development, :test do gem 'rspec-expectations', github: 'rspec/rspec-expectations' gem 'rspec', github: 'rspec/rspec' + gem 'rails-controller-testing' + gem 'factory_girl_rails', '~> 4.5.0' gem 'database_cleaner' - gem 'capybara', '~> 2.3.0' + gem 'capybara' gem 'jasmine-rails', '~> 0.10.2' diff --git a/Gemfile.lock b/Gemfile.lock index 6f166bdd68..838fdc82fe 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,10 @@ +GIT + remote: git://github.com/doorkeeper-gem/doorkeeper.git + revision: 56bfa579484ae9e554028b081227ec8d1b74c21d + specs: + doorkeeper (3.1.0) + railties (>= 4.2) + GIT remote: git://github.com/plataformatec/devise.git revision: cf7c9be6b4129088f9b6457cecf64c6e2a2e0f11 @@ -150,7 +157,8 @@ GEM sidekiq (>= 3.4) capistrano-unicorn (0.2.0) capistrano (< 3.0) - capybara (2.3.0) + capybara (2.6.0) + addressable mime-types (>= 1.16) nokogiri (>= 1.3.3) rack (>= 1.0.0) @@ -212,8 +220,6 @@ GEM devise-encryptable (0.2.0) devise (>= 2.1.0) diff-lcs (1.2.5) - doorkeeper (2.2.2) - railties (>= 3.2) doorkeeper-i18n (3.0.0) dropzonejs-rails (0.7.2) rails (> 3.1) @@ -382,6 +388,8 @@ GEM bundler (>= 1.3.0, < 2.0) railties (= 5.0.0.beta1.1) sprockets-rails (>= 2.0.0) + rails-controller-testing (0.0.3) + rails (>= 4.2) rails-deprecated_sanitizer (1.0.3) activesupport (>= 4.2.0.alpha) rails-dom-testing (1.0.7) @@ -491,7 +499,7 @@ DEPENDENCIES capistrano (= 2.9.0) capistrano-sidekiq capistrano-unicorn - capybara (~> 2.3.0) + capybara carrierwave carrierwave-upyun coffee-rails @@ -501,7 +509,7 @@ DEPENDENCIES derailed devise! devise-encryptable - doorkeeper (~> 2.2.1) + doorkeeper! doorkeeper-i18n dropzonejs-rails elasticsearch-model @@ -536,6 +544,7 @@ DEPENDENCIES rack-mini-profiler rack-utf8_sanitizer rails (= 5.0.0.beta1.1) + rails-controller-testing rails-i18n (~> 5.0.0.beta1) rails-settings-cached rails_autolink diff --git a/app/controllers/likes_controller.rb b/app/controllers/likes_controller.rb index 1583778e18..32f17c04ea 100644 --- a/app/controllers/likes_controller.rb +++ b/app/controllers/likes_controller.rb @@ -4,12 +4,12 @@ class LikesController < ApplicationController def create current_user.like(@item) - render text: @item.reload.likes_count + render plain: @item.reload.likes_count end def destroy current_user.unlike(@item) - render text: @item.reload.likes_count + render plain: @item.reload.likes_count end private @@ -18,7 +18,7 @@ def find_likeable @success = false @element_id = "likeable_#{params[:type]}_#{params[:id]}" unless params[:type].in?(%w(Topic Reply)) - render text: '-1' + render plain: '-1' return false end @@ -32,6 +32,6 @@ def find_likeable end @item = klass.find_by_id(params[:id]) - render text: '-2' if @item.blank? + render plain: '-2' if @item.blank? end end diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index cbe4d4d9b8..fb2fc09046 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -43,7 +43,7 @@ def update end def preview - render text: MarkdownConverter.convert(params[:body]) + render plain: MarkdownConverter.convert(params[:body]) end def destroy diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index f63812d464..59d15198c9 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -75,7 +75,7 @@ def update end def preview - render text: MarkdownConverter.convert(params[:body]) + render plain: MarkdownConverter.convert(params[:body]) end protected diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index fb4843ab4a..b7b4515d89 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -198,24 +198,24 @@ def destroy def favorite current_user.favorite_topic(params[:id]) - render text: '1' + render plain: '1' end def unfavorite current_user.unfavorite_topic(params[:id]) - render text: '1' + render plain: '1' end def follow @topic = Topic.find(params[:id]) @topic.push_follower(current_user.id) - render text: '1' + render plain: '1' end def unfollow @topic = Topic.find(params[:id]) @topic.pull_follower(current_user.id) - render text: '1' + render plain: '1' end def suggest diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 259bc4dc45..9ee426bce3 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -56,7 +56,7 @@ def auth_unbind def update_private_token current_user.update_private_token - render text: current_user.private_token + render plain: current_user.private_token end def city diff --git a/config/routes.rb b/config/routes.rb index ebfddaee7e..935a0c198e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -84,7 +84,7 @@ get '/search' => 'search#index', as: 'search' namespace :cpanel do - root to: 'home#index' + root to: 'home#index', as: 'root' resources :site_configs resources :replies resources :topics do diff --git a/spec/controllers/cpanel/comments_controller_spec.rb b/spec/controllers/cpanel/comments_controller_spec.rb index 4f6b8c8e6f..34108deea2 100644 --- a/spec/controllers/cpanel/comments_controller_spec.rb +++ b/spec/controllers/cpanel/comments_controller_spec.rb @@ -18,7 +18,7 @@ describe 'GET edit' do it 'assigns the requested comment as @comment' do - get :edit, id: comment.id + get :edit, params: { id: comment.id } expect(assigns(:comment)).to eq(comment) end end @@ -26,17 +26,20 @@ describe 'PUT update' do describe 'with valid params' do it 'updates the requested comment' do - expect_any_instance_of(Comment).to receive(:update_attributes).with('body' => 'params') - put :update, id: comment.id, comment: { 'body' => 'params' } + comment_param = { body: '123' } + # expect_any_instance_of(Comment).to receive(:update_attributes).with("body" => '123') + put :update, params: { id: comment.id, comment: comment_param } + comment.reload + expect(comment.body).to eq '123' end it 'assigns the requested comment as @comment' do - put :update, id: comment.id, comment: { 'body' => 'body' } + put :update, params: { id: comment.id, comment: { 'body' => 'body' } } expect(assigns(:comment)).to eq(comment) end it 'redirects to the comment' do - put :update, id: comment.id, comment: { 'body' => 'body' } + put :update, params: { id: comment.id, comment: { 'body' => 'body' } } expect(response).to redirect_to(cpanel_comments_url) end end @@ -46,13 +49,13 @@ it 'destroys the requested comment' do comment expect do - delete :destroy, id: comment.id + delete :destroy, params: { id: comment.id } end.to change(Comment, :count).by(-1) end it 'redirects to the comments list' do comment - delete :destroy, id: comment.id + delete :destroy, params: { id: comment.id } expect(response).to redirect_to(cpanel_comments_url) end end diff --git a/spec/controllers/likes_controller_spec.rb b/spec/controllers/likes_controller_spec.rb index 8d8c6cf4d5..1b30a261f7 100644 --- a/spec/controllers/likes_controller_spec.rb +++ b/spec/controllers/likes_controller_spec.rb @@ -10,26 +10,26 @@ end it 'POST /likes' do - post :create, type: 'Topic', id: topic.id + post :create, params: { type: 'Topic', id: topic.id } expect(response.body).to eq('1') expect(topic.reload.likes_count).to eq(1) - post :create, type: 'Topic', id: topic.id + post :create, params: { type: 'Topic', id: topic.id } expect(response.body).to eq('1') expect(topic.reload.likes_count).to eq(1) allow(controller).to receive(:current_user).and_return(user2) - post :create, type: 'Topic', id: topic.id + post :create, params: { type: 'Topic', id: topic.id } expect(response.body).to eq('2') expect(topic.reload.likes_count).to eq(2) allow(controller).to receive(:current_user).and_return(user) - delete :destroy, type: 'Topic', id: topic.id + delete :destroy, params: { type: 'Topic', id: topic.id } expect(response.body).to eq('1') expect(topic.reload.likes_count).to eq(1) allow(controller).to receive(:current_user).and_return(user2) - delete :destroy, type: 'Topic', id: topic.id + delete :destroy, params: { type: 'Topic', id: topic.id } expect(response.body).to eq('0') expect(topic.reload.likes_count).to eq(0) end @@ -39,21 +39,21 @@ post :create expect(response.status).to eq(302) - delete :destroy, id: 1, type: 'a' + delete :destroy, params: { id: 1, type: 'a' } expect(response.status).to eq(302) end it 'result -1, -2 when params is wrong' do - post :create, type: 'Ask', id: 1 + post :create, params: { type: 'Ask', id: 1 } expect(response.body).to eq('-1') - delete :destroy, type: 'Ask', id: 1 + delete :destroy, params: { type: 'Ask', id: 1 } expect(response.body).to eq('-1') - post :create, type: 'Topic', id: -1 + post :create, params: { type: 'Topic', id: -1 } expect(response.body).to eq('-2') - delete :destroy, type: 'Topic', id: -1 + delete :destroy, params: { type: 'Topic', id: -1 } expect(response.body).to eq('-2') end end diff --git a/spec/controllers/notes_controller_spec.rb b/spec/controllers/notes_controller_spec.rb index ad426813dd..e3f4b0b92f 100644 --- a/spec/controllers/notes_controller_spec.rb +++ b/spec/controllers/notes_controller_spec.rb @@ -30,7 +30,7 @@ describe ':edit' do it 'should have an edit action' do - get :edit, id: note.id + get :edit, params: { id: note.id } expect(assigns[:note]).not_to be_blank expect(response).to be_success end @@ -38,7 +38,7 @@ describe ':show' do it 'should have a show action' do - get :show, id: note.id + get :show, params: { id: note.id } expect(response).to be_success end end diff --git a/spec/controllers/notifications_controller_spec.rb b/spec/controllers/notifications_controller_spec.rb index 20d9efad76..a1ba6e30b7 100644 --- a/spec/controllers/notifications_controller_spec.rb +++ b/spec/controllers/notifications_controller_spec.rb @@ -19,7 +19,7 @@ notification = create :notification_mention, user: user, mentionable: create(:reply) expect do - delete :destroy, id: notification + delete :destroy, params: { id: notification } end.to change(user.notifications, :count) end end diff --git a/spec/controllers/pages_controller_spec.rb b/spec/controllers/pages_controller_spec.rb index 0ae1d268a2..12219c917d 100644 --- a/spec/controllers/pages_controller_spec.rb +++ b/spec/controllers/pages_controller_spec.rb @@ -13,21 +13,21 @@ describe ':show' do it 'should respond with 404 to invalid request made by unauthenticated user' do - get :show, id: 'non_existent' + get :show, params: { id: 'non_existent' } expect(response).not_to be_success expect(response.status).to eq(404) end it 'should prompt user to create new page if page not found but user is logged in' do sign_in user - get :show, id: 'non_existent_yet' + get :show, params: { id: 'non_existent_yet' } expect(response).not_to be_success expect(response.status).to eq(302) expect(response).to redirect_to(new_page_path(title: 'non_existent_yet')) end it 'should respond to valid show action' do - get :show, id: page.slug + get :show, params: { id: page.slug } expect(response).to be_success end end @@ -47,13 +47,13 @@ describe ':edit' do it 'should not allow anonymous access' do - get :edit, id: page.slug + get :edit, params: { id: page.slug } expect(response).not_to be_success end it 'should allowed access from authenticated user' do sign_in user - get :edit, id: page.slug + get :edit, params: { id: page.slug } expect(response).to be_success end end @@ -67,7 +67,7 @@ it 'should create new page if all is well' do sign_in user params = attributes_for(:page).merge(change_desc: "xx") - post :create, page: params + post :create, params: { page: params } expect(response).to redirect_to page_path(params[:slug]) end @@ -75,14 +75,14 @@ sign_in user params = attributes_for(:page) params[:title] = '' - post :create, page: params + post :create, params: { page: params } expect(response).to render_template(:new) end end describe ':update' do it 'should not allow anonymous access' do - put :update, id: 'foo' + put :update, params: { id: 'foo' } expect(response).not_to be_success end @@ -92,7 +92,7 @@ page = Page.create!(params) params[:title] = 'shiney new title' params[:change_desc] = 'updated title' - put :update, page: params, id: page.slug + put :update, params: { page: params, id: page.slug } expect(response).to redirect_to(page_path(page.slug)) end @@ -102,7 +102,7 @@ page = Page.create!(params) params[:title] = 'shiney new title' params[:change_desc] = nil - put :update, page: params, id: page.slug + put :update, params: { page: params, id: page.slug } expect(response).to render_template(:edit) end end @@ -117,7 +117,7 @@ describe ':preview' do it 'should give a text from markdown' do sign_in user - post :preview, body: '123' + post :preview, params: { body: '123' } expect(response.body).to eq("

123

\n") end end diff --git a/spec/controllers/replies_controller_spec.rb b/spec/controllers/replies_controller_spec.rb index 6df1458f05..9b17c6cb31 100644 --- a/spec/controllers/replies_controller_spec.rb +++ b/spec/controllers/replies_controller_spec.rb @@ -9,7 +9,7 @@ create :reply, topic: topic sign_in user - post :create, topic_id: topic.id, reply: { body: 'content' }, format: :js + post :create, params: { topic_id: topic.id, reply: { body: 'content' } }, format: :js expect(response).to be_success expect(user.topic_read?(topic)).to be_truthy expect(assigns(:replies_count)).to eq(topic.reload.replies_count) @@ -23,7 +23,7 @@ it "should not change topic's last reply info to previous one" do sign_in user - post :update, topic_id: topic.id, id: reply.id, reply: { body: 'content' }, format: :js + post :update, params: { topic_id: topic.id, id: reply.id, reply: { body: 'content' } }, format: :js expect(topic.reload.last_reply_user_login).to eq user.login end end @@ -37,28 +37,28 @@ let(:reply1) { create :reply, user: user1, topic: topic } it 'should require login to destroy reply' do - delete :destroy, topic_id: topic.id, id: reply.id + delete :destroy, params: { topic_id: topic.id, id: reply.id } expect(response).not_to be_success end it 'user1 should not allow destroy reply' do sign_in user1 - delete :destroy, topic_id: topic.id, id: reply.id + delete :destroy, params: { topic_id: topic.id, id: reply.id } expect(response).not_to be_success end it 'user should destroy reply with itself' do sign_in user - delete :destroy, topic_id: topic.id, id: reply.id + delete :destroy, params: { topic_id: topic.id, id: reply.id } expect(response).to redirect_to(topic_path(topic)) end it 'admin should destroy reply' do sign_in admin - delete :destroy, topic_id: topic.id, id: reply.id + delete :destroy, params: { topic_id: topic.id, id: reply.id } expect(response).to redirect_to(topic_path(topic)) - delete :destroy, topic_id: topic.id, id: reply1.id + delete :destroy, params: { topic_id: topic.id, id: reply1.id } expect(response).to redirect_to(topic_path(topic)) end end diff --git a/spec/controllers/sites_controller_spec.rb b/spec/controllers/sites_controller_spec.rb index b1661641c5..14167baef0 100644 --- a/spec/controllers/sites_controller_spec.rb +++ b/spec/controllers/sites_controller_spec.rb @@ -33,7 +33,7 @@ let(:site_node) { create :site_node } it 'should not allow anonymous access' do params = attributes_for(:site, site_node_id: site_node.id) - post :create, site: params # avoids ActionController::ParameterMissing + post :create, params: { site: params } # avoids ActionController::ParameterMissing expect(response).not_to be_success end @@ -44,14 +44,14 @@ it 'should create new site if all is well' do params = attributes_for(:site, site_node_id: site_node.id) - post :create, site: params + post :create, params: { site: params } expect(response).to redirect_to(sites_path) end it 'should not create new site if url is blank' do params = attributes_for(:site) params[:url] = '' - post :create, site: params + post :create, params: { site: params } expect(response).to render_template(:new) end end diff --git a/spec/controllers/topics_controller_spec.rb b/spec/controllers/topics_controller_spec.rb index 71fe7fcd60..ee5f94b822 100644 --- a/spec/controllers/topics_controller_spec.rb +++ b/spec/controllers/topics_controller_spec.rb @@ -31,14 +31,14 @@ describe ':node' do it 'should have a node action' do - get :node, id: topic.id + get :node, params: { id: topic.id } expect(response).to be_success end end describe ':node_feed' do it 'should have a node_feed action' do - get :node_feed, id: topic.id + get :node_feed, params: { id: topic.id } expect(response).to be_success end end @@ -69,7 +69,7 @@ describe ':edit' do context 'unauthenticated' do it 'should not allow anonymous access' do - get :edit, id: topic.id + get :edit, params: { id: topic.id } expect(response).not_to be_success end end @@ -78,7 +78,7 @@ context 'own topic' do it 'should allow access from authenticated user' do sign_in user - get :edit, id: topic.id + get :edit, params: { id: topic.id } expect(response).to be_success end end @@ -88,7 +88,7 @@ other_user = create :user topic_of_other_user = create(:topic, user: other_user) sign_in user - get :edit, id: topic_of_other_user.id + get :edit, params: { id: topic_of_other_user.id } expect(response).not_to be_success end end @@ -102,7 +102,7 @@ create :reply, body: "@#{user.login}", topic: topic sign_in user expect do - get :show, id: topic.id + get :show, params: { id: topic.id } end.to change(user.notifications.unread, :count).by(-2) end end @@ -110,13 +110,13 @@ describe '#suggest' do it 'should not allow user suggest' do sign_in user - put :suggest, id: topic + put :suggest, params: { id: topic } expect(topic.reload.excellent).to eq(0) end it 'should not allow user suggest by admin' do sign_in admin - put :suggest, id: topic + put :suggest, params: { id: topic } expect(topic.reload.excellent).to eq(1) end end @@ -127,13 +127,13 @@ it 'should not allow user suggest' do sign_in user - put :unsuggest, id: topic + put :unsuggest, params: { id: topic } expect(topic.reload.excellent).to eq(1) end it 'should not allow user suggest by admin' do sign_in admin - put :unsuggest, id: topic + put :unsuggest, params: { id: topic } expect(topic.reload.excellent).to eq(0) end end @@ -142,13 +142,13 @@ describe '#ban' do it 'should not allow user ban' do sign_in user - post :ban, id: topic + post :ban, params: { id: topic } expect(topic.reload.node_id).not_to eq(Node.no_point_id) end it 'should not allow user suggest by admin' do sign_in admin - post :ban, id: topic + post :ban, params: { id: topic } expect(response.status).to eq(302) expect(topic.reload.node_id).to eq(Node.no_point_id) end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 6d9ceecb31..da5d22b63c 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -6,11 +6,11 @@ describe 'Visit deleted user' do it 'should 404 with deleted user' do - get :show, id: deleted_user.login + get :show, params: { id: deleted_user.login } expect(response.status).to eq(404) - get :topics, id: deleted_user.login + get :topics, params: { id: deleted_user.login } expect(response.status).to eq(404) - get :notes, id: deleted_user.login + get :notes, params: { id: deleted_user.login } expect(response.status).to eq(404) end end @@ -24,55 +24,55 @@ describe ':show' do it 'should show user' do - get :show, id: user.login + get :show, params: { id: user.login } expect(response).to be_success end end describe ':topics' do it 'should show user topics' do - get :topics, id: user.login + get :topics, params: { id: user.login } expect(response).to be_success end end describe ':replies' do it 'should show user replies' do - get :replies, id: user.login + get :replies, params: { id: user.login } expect(response).to be_success end end describe ':favorites' do it 'should show user liked stuffs' do - get :favorites, id: user.login + get :favorites, params: { id: user.login } expect(response).to be_success end end describe ':notes' do it 'should show user notes' do - get :notes, id: user.login + get :notes, params: { id: user.login } expect(response).to be_success end it 'assigns @notes' do note_1 = create(:note, publish: true, user: user) create(:note, publish: false, user: user) - get :notes, id: user.login + get :notes, params: { id: user.login } expect(assigns(:notes)).to eq([note_1]) end end describe ':city' do it 'should render 404 if there is no user in that city' do - get :city, id: 'Mars' + get :city, params: { id: 'Mars' } expect(response).not_to be_success expect(response.status).to eq(404) end it 'should show user associated with that city' do - get :city, id: user.location + get :city, params: { id: user.location } expect(response.status).to eq(200) expect(assigns[:users]).to include(user) end From d3cc32046841e67498a17614e141deacc9c25343 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Thu, 28 Jan 2016 23:02:10 +0800 Subject: [PATCH 04/19] =?UTF-8?q?Fix=20devise=20=E8=BF=87=E6=97=B6?= =?UTF-8?q?=E8=AF=AD=E6=B3=95;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/application_controller.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ffd39416ea..bbe3c5e855 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -9,9 +9,9 @@ class ApplicationController < ActionController::Base params[resource] &&= send(method) if respond_to?(method, true) if devise_controller? - devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(*User::ACCESSABLE_ATTRS) } - devise_parameter_sanitizer.for(:account_update) { |u| u.permit(*User::ACCESSABLE_ATTRS) } - devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(*User::ACCESSABLE_ATTRS) } + devise_parameter_sanitizer.permit(:sign_in) { |u| u.permit(*User::ACCESSABLE_ATTRS) } + devise_parameter_sanitizer.permit(:account_update) { |u| u.permit(*User::ACCESSABLE_ATTRS) } + devise_parameter_sanitizer.permit(:sign_up) { |u| u.permit(*User::ACCESSABLE_ATTRS) } end if current_user From 2f387c8051d536e566044844f9d81817408895c0 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Thu, 28 Jan 2016 23:02:58 +0800 Subject: [PATCH 05/19] Fix users route --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 935a0c198e..64c9e8dc94 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -135,7 +135,7 @@ get 'users/city/:id' => 'users#city', as: 'location_users' get 'users' => 'users#index', as: 'users' - resources :users, path: '' do + resources :users, path: '', as: 'users' do member do get :topics get :replies From 7496677f25b7ace0d75b1d5e8d30861ac4387e99 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Thu, 28 Jan 2016 23:03:20 +0800 Subject: [PATCH 06/19] Upgrade rack-mini-profiler for Rack 2.0 --- Gemfile | 2 +- Gemfile.lock | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index 9800e1506d..db9bab2b8c 100644 --- a/Gemfile +++ b/Gemfile @@ -113,7 +113,7 @@ gem 'rack-cors', require: 'rack/cors' gem 'rack-utf8_sanitizer' # Mini profiler -gem 'rack-mini-profiler', require: false +gem 'rack-mini-profiler', github: 'MiniProfiler/rack-mini-profiler', require: false gem 'oneapm_rpm' diff --git a/Gemfile.lock b/Gemfile.lock index 838fdc82fe..0d5b72b6b5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,10 @@ +GIT + remote: git://github.com/MiniProfiler/rack-mini-profiler.git + revision: cb7a6cf4d4cd7febb587bcffb4719233034c331b + specs: + rack-mini-profiler (0.9.8) + rack (>= 1.2.0) + GIT remote: git://github.com/doorkeeper-gem/doorkeeper.git revision: 56bfa579484ae9e554028b081227ec8d1b74c21d @@ -368,8 +375,6 @@ GEM rack-accept (0.4.5) rack (>= 0.4) rack-cors (0.4.0) - rack-mini-profiler (0.9.8) - rack (>= 1.1.3) rack-mount (0.8.3) rack (>= 1.0.0) rack-test (0.6.3) @@ -541,7 +546,7 @@ DEPENDENCIES postmark-rails puma rack-cors - rack-mini-profiler + rack-mini-profiler! rack-utf8_sanitizer rails (= 5.0.0.beta1.1) rails-controller-testing From 11497a120b3850a7350ebbe9e7a8b8357ed6b3fe Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Thu, 28 Jan 2016 23:31:17 +0800 Subject: [PATCH 07/19] jQuery 2.0 --- app/assets/javascripts/app.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/app.coffee b/app/assets/javascripts/app.coffee index e917a7aab1..8615e1a947 100644 --- a/app/assets/javascripts/app.coffee +++ b/app/assets/javascripts/app.coffee @@ -1,4 +1,4 @@ -#= require jquery +#= require jquery2 #= require jquery.turbolinks #= require jquery_ujs #= require bootstrap.min From 09b7700547c83e58349a4af7e6fbc63f68c7678c Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Thu, 28 Jan 2016 23:39:10 +0800 Subject: [PATCH 08/19] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20Fragment=20cache=20?= =?UTF-8?q?=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/helpers/application_helper.rb | 3 ++- app/views/home/api.html.erb | 2 +- app/views/sites/index.html.erb | 2 +- app/views/topics/index.html.erb | 6 +++--- config/environments/development.rb | 17 +++++------------ 5 files changed, 12 insertions(+), 18 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index d987f66f30..de3cea93e6 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -168,7 +168,8 @@ def cached_asset_path(name) end # Override cache helper for support multiple I18n locale - def cache(name = {}, options = nil, &block) + def cache(name = {}, options = {}, &block) + options ||= {} super([I18n.locale, name], options, &block) end diff --git a/app/views/home/api.html.erb b/app/views/home/api.html.erb index 2948223ec2..9dcd082aa3 100644 --- a/app/views/home/api.html.erb +++ b/app/views/home/api.html.erb @@ -1,4 +1,4 @@ -<% cache(["api", "v3.10"], expires_in: 1.days) do %> +<% cache(["api", "v3.10", Date.today]) do %>
Ruby China API 目录
diff --git a/app/views/sites/index.html.erb b/app/views/sites/index.html.erb index e0d530735f..e960c7217a 100644 --- a/app/views/sites/index.html.erb +++ b/app/views/sites/index.html.erb @@ -8,7 +8,7 @@
<% end %> - <% cache(["sites/list", t: CacheVersion.sites_updated_at], expires_in: 1.days) do %> + <% cache(["sites/list", t: CacheVersion.sites_updated_at, d: Date.today]) do %> <% @site_nodes.each do |node| %>
<%= node.name %>
diff --git a/app/views/topics/index.html.erb b/app/views/topics/index.html.erb index e35c6ae0c9..8d228894c3 100644 --- a/app/views/topics/index.html.erb +++ b/app/views/topics/index.html.erb @@ -7,13 +7,13 @@
<% if @topics.current_page == 1 %> - <% cache(['suggest_topics', @suggest_topics]) do %> + <% cache(['suggest_topics', @suggest_topics.to_a]) do %> <%= render partial: "topics/topic", collection: @suggest_topics, locals: { suggest: true } %> <% end %> <% end %> - <% cache(['topics', @topics]) do %> - <%= render partial: "topics/topic", collection: @topics, locals: { suggest: false } %> + <% cache(['topics', @topics.to_a]) do %> + <%= render @topics, suggest: false %> <% end %>
diff --git a/config/environments/development.rb b/config/environments/development.rb index b22ceceaea..fd9d9f7ae7 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -11,19 +11,12 @@ # Show full error reports. config.consider_all_requests_local = true - config.action_controller.perform_caching = true # Enable/disable caching. By default caching is disabled. - if Rails.root.join('tmp/caching-dev.txt').exist? - config.action_controller.perform_caching = true - config.cache_store = :memory_store - config.public_file_server.headers = { - 'Cache-Control' => 'public, max-age=172800' - } - else - config.action_controller.perform_caching = false - config.cache_store = :null_store - end + config.action_controller.perform_caching = true + config.public_file_server.headers = { + 'Cache-Control' => 'public, max-age=172800' + } # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false @@ -37,7 +30,7 @@ # Debug mode disables concatenation and preprocessing of assets. # This option may cause significant delays in view rendering with a large # number of complex assets. - config.assets.debug = true + config.assets.debug = false # Asset digests allow you to set far-future HTTP expiration dates on all assets, # yet still be able to expire them through the digest params. From 6bd38866198fc02c90bbf10ecdfd120b14df1ecb Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Sun, 31 Jan 2016 18:09:17 +0800 Subject: [PATCH 09/19] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20Sidekiq=20Web?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile | 2 +- Gemfile.lock | 12 ++++++++++++ config/routes.rb | 8 ++++---- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index db9bab2b8c..40dbb13c56 100644 --- a/Gemfile +++ b/Gemfile @@ -81,7 +81,7 @@ gem 'settingslogic' # 队列 gem 'sidekiq' # Sidekiq Web -# gem 'sinatra', require: nil +gem 'sinatra', github: 'sinatra/sinatra', require: nil gem 'message_bus' diff --git a/Gemfile.lock b/Gemfile.lock index 0d5b72b6b5..2deca58b8d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -81,6 +81,15 @@ GIT rspec-expectations (= 3.5.0.pre) rspec-mocks (= 3.5.0.pre) +GIT + remote: git://github.com/sinatra/sinatra.git + revision: f8d4e9b332c15c22cbe8bad32aefbeeaaaed1e3f + specs: + sinatra (2.0.0.pre.alpha) + rack (= 2.0.0.alpha) + rack-protection (~> 1.5) + tilt (~> 2.0) + GEM remote: https://ruby.taobao.org/ specs: @@ -377,6 +386,8 @@ GEM rack-cors (0.4.0) rack-mount (0.8.3) rack (>= 1.0.0) + rack-protection (1.5.3) + rack rack-test (0.6.3) rack (>= 1.0) rack-utf8_sanitizer (1.3.2) @@ -571,6 +582,7 @@ DEPENDENCIES settingslogic sidekiq simple_form + sinatra! social-share-button sprockets turbolinks! diff --git a/config/routes.rb b/config/routes.rb index 64c9e8dc94..013fca3bb7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -123,10 +123,10 @@ mount API::Dispatch => '/api' - # require 'sidekiq/web' - # authenticate :user, ->(u) { u.admin? } do - # mount Sidekiq::Web => '/sidekiq' - # end + require 'sidekiq/web' + authenticate :user, ->(u) { u.admin? } do + mount Sidekiq::Web => '/sidekiq' + end mount JasmineRails::Engine => '/specs' if defined?(JasmineRails) From 6e18706c34aed9da1bf1351bd907cf13c28470c9 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Sun, 31 Jan 2016 18:15:02 +0800 Subject: [PATCH 10/19] Change Travis CI to use PostgreSQL 9.4 --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 87bbe23f7c..51e8a1f46b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,9 @@ language: ruby env: - USE_OFFICIAL_GEM_SOURCE=1 +addons: + postgresql: "9.4" + services: - postgresql - memcached From 7c9b8a2195ff08eef1dd356a1670e165dbb0b7c7 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Tue, 2 Feb 2016 10:34:06 +0800 Subject: [PATCH 11/19] Upgrade CanCanCan to 1.13.1 --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 40dbb13c56..1afaed401c 100644 --- a/Gemfile +++ b/Gemfile @@ -58,7 +58,7 @@ gem 'omniauth' gem 'omniauth-github' # permission -gem 'cancancan', '~> 1.8.4' +gem 'cancancan', '~> 1.13.1' gem 'redis' gem 'hiredis' diff --git a/Gemfile.lock b/Gemfile.lock index 2deca58b8d..03d0511ca9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -161,7 +161,7 @@ GEM bundler-audit (0.4.0) bundler (~> 1.2) thor (~> 0.18) - cancancan (1.8.4) + cancancan (1.13.1) capistrano (2.9.0) highline net-scp (>= 1.0.0) @@ -511,7 +511,7 @@ DEPENDENCIES better_errors binding_of_caller bundler-audit - cancancan (~> 1.8.4) + cancancan (~> 1.13.1) capistrano (= 2.9.0) capistrano-sidekiq capistrano-unicorn From 3f2a29586e8bc1ed7c0735a416133953af436f88 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Tue, 2 Feb 2016 11:01:40 +0800 Subject: [PATCH 12/19] Rails 5.0.0.beta2, Devise 4.0.0.rc1 --- Gemfile | 6 +- Gemfile.lock | 134 +++++++++++++---------------------- config/{redis => }/cable.yml | 0 3 files changed, 52 insertions(+), 88 deletions(-) rename config/{redis => }/cable.yml (100%) diff --git a/Gemfile b/Gemfile index 1afaed401c..3562970848 100644 --- a/Gemfile +++ b/Gemfile @@ -6,7 +6,7 @@ end ruby '2.3.0' -gem 'rails', '5.0.0.beta1.1' +gem 'rails', '5.0.0.beta2' gem 'sprockets' gem 'sass-rails' gem 'coffee-rails' @@ -17,7 +17,7 @@ gem 'turbolinks', github: 'rails/turbolinks' gem 'jquery-turbolinks' gem 'dropzonejs-rails' -gem 'rails-i18n', '~> 5.0.0.beta1' +gem 'rails-i18n' gem 'http_accept_language' gem 'rails_autolink' gem 'md_emoji' @@ -43,7 +43,7 @@ gem 'pg' gem 'mongo', require: false # 用户系统 -gem 'devise', github: 'plataformatec/devise' +gem 'devise', '~> 4.0.0.rc1' gem 'devise-encryptable' # 分页 diff --git a/Gemfile.lock b/Gemfile.lock index 03d0511ca9..c037edf135 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -12,17 +12,6 @@ GIT doorkeeper (3.1.0) railties (>= 4.2) -GIT - remote: git://github.com/plataformatec/devise.git - revision: cf7c9be6b4129088f9b6457cecf64c6e2a2e0f11 - specs: - devise (4.0.0.pre.dev) - bcrypt (~> 3.0) - orm_adapter (~> 0.1) - railties (>= 4.1.0, < 5.1) - responders - warden (~> 1.2.3) - GIT remote: git://github.com/rails/turbolinks.git revision: dd31f4b2996f2300631f89339ada82c65b95f4c2 @@ -39,7 +28,7 @@ GIT GIT remote: git://github.com/rspec/rspec-expectations.git - revision: e7b08da715a777320586dec9f6c2ae5c44585ddd + revision: 4c1856b5155f14b4fa5f2c623f2e3fe92bbd1463 specs: rspec-expectations (3.5.0.pre) diff-lcs (>= 1.2.0, < 2.0) @@ -55,7 +44,7 @@ GIT GIT remote: git://github.com/rspec/rspec-rails.git - revision: 44e5b8a927c35397bdbf36a6a99fbb9a567f25b8 + revision: f37065600822e49df993e58e86b07d54e4af3fd8 specs: rspec-rails (3.5.0.pre) actionpack (>= 3.0) @@ -91,48 +80,43 @@ GIT tilt (~> 2.0) GEM - remote: https://ruby.taobao.org/ + remote: https://rubygems.org/ specs: - actioncable (5.0.0.beta1.1) - actionpack (= 5.0.0.beta1.1) - celluloid (~> 0.17.2) - coffee-rails (~> 4.1.0) - em-hiredis (~> 0.3.0) - faye-websocket (~> 0.10.0) - redis (~> 3.0) + actioncable (5.0.0.beta2) + actionpack (= 5.0.0.beta2) + nio4r (~> 1.2) websocket-driver (~> 0.6.1) - actionmailer (5.0.0.beta1.1) - actionpack (= 5.0.0.beta1.1) - actionview (= 5.0.0.beta1.1) - activejob (= 5.0.0.beta1.1) + actionmailer (5.0.0.beta2) + actionpack (= 5.0.0.beta2) + actionview (= 5.0.0.beta2) + activejob (= 5.0.0.beta2) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (5.0.0.beta1.1) - actionview (= 5.0.0.beta1.1) - activesupport (= 5.0.0.beta1.1) + actionpack (5.0.0.beta2) + actionview (= 5.0.0.beta2) + activesupport (= 5.0.0.beta2) rack (~> 2.x) rack-test (~> 0.6.3) rails-dom-testing (~> 1.0, >= 1.0.5) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.0.0.beta1.1) - activesupport (= 5.0.0.beta1.1) + actionview (5.0.0.beta2) + activesupport (= 5.0.0.beta2) builder (~> 3.1) erubis (~> 2.7.0) rails-dom-testing (~> 1.0, >= 1.0.5) rails-html-sanitizer (~> 1.0, >= 1.0.2) active_model_serializers (0.9.2) activemodel (>= 3.2) - activejob (5.0.0.beta1.1) - activesupport (= 5.0.0.beta1.1) + activejob (5.0.0.beta2) + activesupport (= 5.0.0.beta2) globalid (>= 0.3.6) - activemodel (5.0.0.beta1.1) - activesupport (= 5.0.0.beta1.1) - builder (~> 3.1) - activerecord (5.0.0.beta1.1) - activemodel (= 5.0.0.beta1.1) - activesupport (= 5.0.0.beta1.1) + activemodel (5.0.0.beta2) + activesupport (= 5.0.0.beta2) + activerecord (5.0.0.beta2) + activemodel (= 5.0.0.beta2) + activesupport (= 5.0.0.beta2) arel (~> 7.0) - activesupport (5.0.0.beta1.1) + activesupport (5.0.0.beta2) concurrent-ruby (~> 1.0) i18n (~> 0.7) json (~> 1.7, >= 1.7.7) @@ -188,23 +172,6 @@ GEM carrierwave-upyun (0.2.1) carrierwave (>= 0.5.7) faraday (>= 0.8.0) - celluloid (0.17.3) - celluloid-essentials - celluloid-extras - celluloid-fsm - celluloid-pool - celluloid-supervision - timers (>= 4.1.1) - celluloid-essentials (0.20.5) - timers (>= 4.1.1) - celluloid-extras (0.20.5) - timers (>= 4.1.1) - celluloid-fsm (0.20.5) - timers (>= 4.1.1) - celluloid-pool (0.20.5) - timers (>= 4.1.1) - celluloid-supervision (0.20.5) - timers (>= 4.1.1) coderay (1.1.0) coercible (1.0.0) descendants_tracker (~> 0.0.1) @@ -233,6 +200,12 @@ GEM thor (~> 0.19) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) + devise (4.0.0.rc1) + bcrypt (~> 3.0) + orm_adapter (~> 0.1) + railties (>= 4.1.0, < 5.1) + responders + warden (~> 1.2.3) devise-encryptable (0.2.0) devise (>= 2.1.0) diff-lcs (1.2.5) @@ -252,12 +225,8 @@ GEM elasticsearch-transport (1.0.15) faraday multi_json - em-hiredis (0.3.0) - eventmachine (~> 1.0) - hiredis (~> 0.5.0) equalizer (0.0.11) erubis (2.7.0) - eventmachine (1.0.9.1) exception_notification (4.1.1) actionmailer (>= 3.0.4) activesupport (>= 3.0.4) @@ -269,9 +238,6 @@ GEM railties (>= 3.0.0) faraday (0.9.2) multipart-post (>= 1.2, < 3) - faye-websocket (0.10.2) - eventmachine (>= 0.12.0) - websocket-driver (>= 0.5.1) get_process_mem (0.2.0) globalid (0.3.6) activesupport (>= 4.1.0) @@ -291,8 +257,7 @@ GEM hashie (3.4.3) heapy (0.1.2) highline (1.7.8) - hiredis (0.5.2) - hitimes (1.2.3) + hiredis (0.6.1) http_accept_language (2.0.5) httpauth (0.2.1) i18n (0.7.0) @@ -348,6 +313,7 @@ GEM net-ssh (3.0.2) net-ssh-gateway (1.2.0) net-ssh (>= 2.6.5) + nio4r (1.2.1) nokogiri (1.6.7.2) mini_portile2 (~> 2.0.0.rc2) oauth2 (0.6.1) @@ -392,17 +358,17 @@ GEM rack (>= 1.0) rack-utf8_sanitizer (1.3.2) rack (>= 1.0, < 3.0) - rails (5.0.0.beta1.1) - actioncable (= 5.0.0.beta1.1) - actionmailer (= 5.0.0.beta1.1) - actionpack (= 5.0.0.beta1.1) - actionview (= 5.0.0.beta1.1) - activejob (= 5.0.0.beta1.1) - activemodel (= 5.0.0.beta1.1) - activerecord (= 5.0.0.beta1.1) - activesupport (= 5.0.0.beta1.1) + rails (5.0.0.beta2) + actioncable (= 5.0.0.beta2) + actionmailer (= 5.0.0.beta2) + actionpack (= 5.0.0.beta2) + actionview (= 5.0.0.beta2) + activejob (= 5.0.0.beta2) + activemodel (= 5.0.0.beta2) + activerecord (= 5.0.0.beta2) + activesupport (= 5.0.0.beta2) bundler (>= 1.3.0, < 2.0) - railties (= 5.0.0.beta1.1) + railties (= 5.0.0.beta2) sprockets-rails (>= 2.0.0) rails-controller-testing (0.0.3) rails (>= 4.2) @@ -421,9 +387,9 @@ GEM rails (>= 4.2.0) rails_autolink (1.1.6) rails (> 3.1) - railties (5.0.0.beta1.1) - actionpack (= 5.0.0.beta1.1) - activesupport (= 5.0.0.beta1.1) + railties (5.0.0.beta2) + actionpack (= 5.0.0.beta2) + activesupport (= 5.0.0.beta2) method_source rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) @@ -470,15 +436,13 @@ GEM sprockets (3.5.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.0.0) + sprockets-rails (3.0.1) actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) thor (0.19.1) thread_safe (0.3.5) tilt (2.0.2) - timers (4.1.1) - hitimes tzinfo (1.2.2) thread_safe (~> 0.1) uglifier (2.7.2) @@ -493,7 +457,7 @@ GEM coercible (~> 1.0) descendants_tracker (~> 0.0, >= 0.0.3) equalizer (~> 0.0, >= 0.0.9) - warden (1.2.4) + warden (1.2.6) rack (>= 1.0) websocket-driver (0.6.3) websocket-extensions (>= 0.1.0) @@ -523,7 +487,7 @@ DEPENDENCIES dalli database_cleaner derailed - devise! + devise (~> 4.0.0.rc1) devise-encryptable doorkeeper! doorkeeper-i18n @@ -559,9 +523,9 @@ DEPENDENCIES rack-cors rack-mini-profiler! rack-utf8_sanitizer - rails (= 5.0.0.beta1.1) + rails (= 5.0.0.beta2) rails-controller-testing - rails-i18n (~> 5.0.0.beta1) + rails-i18n rails-settings-cached rails_autolink redcarpet (~> 3.3.4) diff --git a/config/redis/cable.yml b/config/cable.yml similarity index 100% rename from config/redis/cable.yml rename to config/cable.yml From 7193062fa3b8538af504ba470a23442dbdc01896 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Tue, 2 Feb 2016 11:50:57 +0800 Subject: [PATCH 13/19] =?UTF-8?q?=E7=94=A8=20ActionCable=20=E4=BB=A3?= =?UTF-8?q?=E6=9B=BF=20MessageBus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile | 6 +-- Gemfile.lock | 12 +---- app/assets/javascripts/app.coffee | 47 ++++++++++---------- app/channels/application_cable/channel.rb | 4 ++ app/channels/application_cable/connection.rb | 18 ++++++++ app/channels/notification_channel.rb | 8 ++++ app/controllers/application_controller.rb | 4 ++ app/models/notification/base.rb | 2 +- config.ru | 1 - config/routes.rb | 2 +- 10 files changed, 61 insertions(+), 43 deletions(-) create mode 100644 app/channels/application_cable/channel.rb create mode 100644 app/channels/application_cable/connection.rb create mode 100644 app/channels/notification_channel.rb diff --git a/Gemfile b/Gemfile index 3562970848..854b5442f6 100644 --- a/Gemfile +++ b/Gemfile @@ -83,8 +83,6 @@ gem 'sidekiq' # Sidekiq Web gem 'sinatra', github: 'sinatra/sinatra', require: nil -gem 'message_bus' - # 分享功能 gem 'social-share-button' @@ -104,7 +102,7 @@ gem 'postmark-rails' gem 'kgio' gem 'dalli' -gem 'unicorn' +gem 'puma' gem 'parallel' @@ -118,8 +116,6 @@ gem 'rack-mini-profiler', github: 'MiniProfiler/rack-mini-profiler', require: fa gem 'oneapm_rpm' group :development do - gem 'puma' - gem 'capistrano', '2.9.0', require: false gem 'capistrano-unicorn' gem 'rvm-capistrano', require: false diff --git a/Gemfile.lock b/Gemfile.lock index c037edf135..d5394f8d3f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -80,7 +80,7 @@ GIT tilt (~> 2.0) GEM - remote: https://rubygems.org/ + remote: https://ruby.taobao.org/ specs: actioncable (5.0.0.beta2) actionpack (= 5.0.0.beta2) @@ -293,9 +293,6 @@ GEM railties (>= 3.1.0) redcarpet (>= 2.0) memory_profiler (0.9.6) - message_bus (1.1.1) - rack (>= 1.1.3) - redis method_source (0.8.2) mime-types (2.99) mini_magick (4.3.6) @@ -394,7 +391,6 @@ GEM rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rainbow (2.1.0) - raindrops (0.15.0) rake (10.5.0) redcarpet (3.3.4) redis (3.2.2) @@ -448,10 +444,6 @@ GEM uglifier (2.7.2) execjs (>= 0.3.0) json (>= 1.8.0) - unicorn (5.0.1) - kgio (~> 2.6) - rack - raindrops (~> 0.7) virtus (1.0.5) axiom-types (~> 0.1) coercible (~> 1.0) @@ -508,7 +500,6 @@ DEPENDENCIES letter_avatar letter_opener md_emoji - message_bus mini_magick mongo nokogiri @@ -551,7 +542,6 @@ DEPENDENCIES sprockets turbolinks! uglifier - unicorn will_paginate BUNDLED WITH diff --git a/app/assets/javascripts/app.coffee b/app/assets/javascripts/app.coffee index 8615e1a947..dd7673de8c 100644 --- a/app/assets/javascripts/app.coffee +++ b/app/assets/javascripts/app.coffee @@ -16,7 +16,7 @@ #= require jquery.atwho #= require emoji_list #= require notifier -#= require message-bus +#= require action_cable #= require form_storage #= require topics #= require pages @@ -43,7 +43,7 @@ AppView = Backbone.View.extend Turbolinks.ProgressBar.enable() @initForDesktopView() @initComponents() - @initNotificationSubscribe() + @initCabe() if $('body').data('controller-name') in ['topics', 'replies'] window._topicView = new TopicView({parentView: @}) @@ -122,28 +122,27 @@ AppView = Backbone.View.extend $('span',el).text("#{likes_count} 个赞") $("i.fa",el).attr("class","fa fa-thumbs-up") - - initNotificationSubscribe : () -> - return if not App.access_token? - return if App.access_token.length < 5 - MessageBus.start() - MessageBus.callbackInterval = 1000 - MessageBus.subscribe "/notifications_count/#{App.access_token}", (json) -> - span = $(".notification-count span") - link = $(".notification-count a") - new_title = document.title.replace(/^\(\d+\) /,'') - if json.count > 0 - span.show() - new_title = "(#{json.count}) #{new_title}" - url = App.fixUrlDash("#{App.root_url}#{json.content_path}") - $.notifier.notify("",json.title,json.content,url) - link.addClass("new") - else - span.hide() - link.removeClass("new") - span.text(json.count) - document.title = new_title - true + initCabe: () -> + @cable = ActionCable.createConsumer("/cable") + @notification = @cable.subscriptions.create "NotificationChannel", + received: (data) => + @receivedNotificationCount(data) + + receivedNotificationCount : (json) -> + span = $(".notification-count span") + link = $(".notification-count a") + new_title = document.title.replace(/^\(\d+\) /,'') + if json.count > 0 + span.show() + new_title = "(#{json.count}) #{new_title}" + url = App.fixUrlDash("#{App.root_url}#{json.content_path}") + $.notifier.notify("",json.title,json.content,url) + link.addClass("new") + else + span.hide() + link.removeClass("new") + span.text(json.count) + document.title = new_title openHeaderSearchBox: (e) -> $(".header .form-search").addClass("active") diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb new file mode 100644 index 0000000000..d672697283 --- /dev/null +++ b/app/channels/application_cable/channel.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Channel < ActionCable::Channel::Base + end +end diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb new file mode 100644 index 0000000000..d107f38f74 --- /dev/null +++ b/app/channels/application_cable/connection.rb @@ -0,0 +1,18 @@ +module ApplicationCable + class Connection < ActionCable::Connection::Base + identified_by :current_user + + def connect + self.current_user = find_verified_user + end + + protected + def find_verified_user + if current_user = User.find_by(id: cookies.signed[:user_id]) + current_user + else + reject_unauthorized_connection + end + end + end +end diff --git a/app/channels/notification_channel.rb b/app/channels/notification_channel.rb new file mode 100644 index 0000000000..93d3981c92 --- /dev/null +++ b/app/channels/notification_channel.rb @@ -0,0 +1,8 @@ +class NotificationChannel < ApplicationCable::Channel + def subscribed + stream_from "notifications_count/#{current_user.id}" + end + + def unsubscribed + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index bbe3c5e855..edd2011362 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -8,6 +8,10 @@ class ApplicationController < ActionController::Base method = "#{resource}_params" params[resource] &&= send(method) if respond_to?(method, true) + if current_user + cookies.signed[:user_id] ||= current_user.id + end + if devise_controller? devise_parameter_sanitizer.permit(:sign_in) { |u| u.permit(*User::ACCESSABLE_ATTRS) } devise_parameter_sanitizer.permit(:account_update) { |u| u.permit(*User::ACCESSABLE_ATTRS) } diff --git a/app/models/notification/base.rb b/app/models/notification/base.rb index 50bc77dd5f..c6539441db 100644 --- a/app/models/notification/base.rb +++ b/app/models/notification/base.rb @@ -15,7 +15,7 @@ def realtime_push_to_client if user hash = notify_hash hash[:count] = user.notifications.unread.count - MessageBus.publish "/notifications_count/#{user.temp_access_token}", hash + ActionCable.server.broadcast "notifications_count/#{user.id}", hash end end diff --git a/config.ru b/config.ru index 97af810d95..bdecdce931 100644 --- a/config.ru +++ b/config.ru @@ -4,7 +4,6 @@ require ::File.expand_path('../config/environment', __FILE__) # Action Cable uses EventMachine which requires that all classes are loaded in advance Rails.application.eager_load! -# require 'action_cable/process/logging' run Rails.application diff --git a/config/routes.rb b/config/routes.rb index 013fca3bb7..ab204103e3 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,7 +2,7 @@ # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html # Serve websocket cable requests in-process - # mount ActionCable.server => '/cable' + mount ActionCable.server => '/cable' mount RuCaptcha::Engine => "/rucaptcha" use_doorkeeper do From 689b7ca735b4f024d8aabc1ebb16a55acf5d506c Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Tue, 2 Feb 2016 11:54:36 +0800 Subject: [PATCH 14/19] =?UTF-8?q?Unicorn=20->=20Puma,=20ActionCable=20?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E5=A4=9A=E7=BA=BF=E7=A8=8B=E7=9A=84=20App=20?= =?UTF-8?q?Server?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile | 1 - Gemfile.lock | 5 +---- config/deploy.rb | 14 +++++++----- config/puma.rb | 7 ++++++ config/unicorn.rb | 56 ----------------------------------------------- 5 files changed, 17 insertions(+), 66 deletions(-) create mode 100644 config/puma.rb delete mode 100644 config/unicorn.rb diff --git a/Gemfile b/Gemfile index 854b5442f6..6d34eab0ed 100644 --- a/Gemfile +++ b/Gemfile @@ -117,7 +117,6 @@ gem 'oneapm_rpm' group :development do gem 'capistrano', '2.9.0', require: false - gem 'capistrano-unicorn' gem 'rvm-capistrano', require: false gem 'capistrano-sidekiq' diff --git a/Gemfile.lock b/Gemfile.lock index d5394f8d3f..1a2d29cc07 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -155,8 +155,6 @@ GEM capistrano-sidekiq (0.5.4) capistrano sidekiq (>= 3.4) - capistrano-unicorn (0.2.0) - capistrano (< 3.0) capybara (2.6.0) addressable mime-types (>= 1.16) @@ -341,7 +339,7 @@ GEM actionmailer (>= 3.0.0) postmark (~> 1.7.0) powerpack (0.1.1) - puma (2.15.3) + puma (2.16.0) rack (2.0.0.alpha) json rack-accept (0.4.5) @@ -470,7 +468,6 @@ DEPENDENCIES cancancan (~> 1.13.1) capistrano (= 2.9.0) capistrano-sidekiq - capistrano-unicorn capybara carrierwave carrierwave-upyun diff --git a/config/deploy.rb b/config/deploy.rb index a248556bf2..5d4bcb0d60 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -1,7 +1,8 @@ require 'bundler/capistrano' require 'capistrano/sidekiq' require 'rvm/capistrano' -require 'capistrano-unicorn' +require 'puma' +require 'puma/capistrano' default_run_options[:pty] = true @@ -16,7 +17,9 @@ set :runner, 'ruby' # set :deploy_via, :remote_cache set :git_shallow_clone, 1 -set :unicorn_pid, "#{current_path}/tmp/pids/unicorn.pid" + +set :puma_role, :app +set :puma_config_file, "config/puma.rb" role :web, 'ruby-china.org' role :app, 'ruby-china.org' @@ -47,6 +50,7 @@ end after 'deploy:finalize_update', 'deploy:symlink', :link_shared, :migrate_db#, :compile_assets -after 'deploy:restart', 'unicorn:restart' -after 'deploy:start', 'unicorn:start' -after 'deploy:stop', 'unicorn:stop' +after 'deploy:restart', 'puma:restart' +after 'deploy:start', 'puma:start' +after 'deploy:stop', 'puma:stop' + diff --git a/config/puma.rb b/config/puma.rb new file mode 100644 index 0000000000..dbe229e87d --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,7 @@ +app_root = '/home/ruby/www/ruby-china/current' +pidfile "#{app_root}/tmp/pids/puma.pid" +state_path "#{app_root}/tmp/pids/puma.state" +daemonize true +workers 4 +threads 16,64 +preload_app! diff --git a/config/unicorn.rb b/config/unicorn.rb deleted file mode 100644 index 38358d76f4..0000000000 --- a/config/unicorn.rb +++ /dev/null @@ -1,56 +0,0 @@ -require 'etc' - -root = File.expand_path('../../', __FILE__) - -working_directory root -pid "#{root}/tmp/pids/unicorn.pid" -stderr_path "#{root}/log/unicorn.log" -stdout_path "#{root}/log/unicorn.log" - -listen 7000, tcp_nopush: true -listen '/tmp/unicorn.ruby-china.sock', backlog: 1024 -# Use number of CPU cores -worker_processes Etc.nprocessors + 1 -# Because there have upload feature. -timeout 120 - -preload_app true -GC.respond_to?(:copy_on_write_friendly=) && GC.copy_on_write_friendly = true - -check_client_connection false - -before_exec do |_server| - ENV['BUNDLE_GEMFILE'] = "#{root}/Gemfile" -end - -before_fork do |server, _worker| - old_pid = "#{server.config[:pid]}.oldbin" - if File.exist?(old_pid) && server.pid != old_pid - begin - Process.kill('QUIT', File.read(old_pid).to_i) - rescue Errno::ENOENT, Errno::ESRCH - puts "Send 'QUIT' signal to unicorn error!" - end - end - - if defined?(ActiveRecord::Base) - ActiveRecord::Base.connection.disconnect! - end - - Signal.trap 'TERM' do - puts 'Unicorn master intercepting TERM and sending myself QUIT instead' - Process.kill 'QUIT', Process.pid - end -end - -after_fork do |_server, _worker| - MessageBus.after_fork - - if defined?(ActiveRecord::Base) - ActiveRecord::Base.establish_connection - end - - Signal.trap 'TERM' do - puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT' - end -end From f4c38d9b940e0ff24e8922c8db0ed65aa9638d03 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Tue, 2 Feb 2016 14:44:16 +0800 Subject: [PATCH 15/19] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E8=AF=9D=E9=A2=98?= =?UTF-8?q?=E6=9F=A5=E7=9C=8B=E7=95=8C=E9=9D=A2=E6=96=B0=E5=9B=9E=E5=A4=8D?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E6=8F=90=E9=86=92=EF=BC=8C=E7=82=B9=E5=87=BB?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E6=97=A0=E5=88=B7=E6=96=B0=E8=BD=BD=E5=85=A5?= =?UTF-8?q?=E6=96=B0=E5=86=85=E5=AE=B9;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/assets/javascripts/app.coffee | 4 +-- app/assets/javascripts/topics.coffee | 30 +++++++++++++++++++ app/assets/stylesheets/application.scss | 10 +++++++ ...on_channel.rb => notifications_channel.rb} | 2 +- app/channels/replies_channel.rb | 8 +++++ app/controllers/replies_controller.rb | 7 +++++ app/models/reply.rb | 6 ++++ app/views/replies/_create_callback.js.erb | 17 +++++++++++ app/views/replies/_reply.html.erb | 2 +- app/views/replies/create.js.erb | 23 ++++---------- app/views/replies/index.js.erb | 3 ++ app/views/topics/show.html.erb | 5 ++++ config/environments/development.rb | 1 + spec/controllers/replies_controller_spec.rb | 9 ++++++ spec/models/notification/base_spec.rb | 15 ++++++++++ spec/models/reply_spec.rb | 17 +++++++++++ 16 files changed, 138 insertions(+), 21 deletions(-) rename app/channels/{notification_channel.rb => notifications_channel.rb} (66%) create mode 100644 app/channels/replies_channel.rb create mode 100644 app/views/replies/_create_callback.js.erb create mode 100644 app/views/replies/index.js.erb create mode 100644 spec/models/notification/base_spec.rb diff --git a/app/assets/javascripts/app.coffee b/app/assets/javascripts/app.coffee index dd7673de8c..0d354d88ed 100644 --- a/app/assets/javascripts/app.coffee +++ b/app/assets/javascripts/app.coffee @@ -123,8 +123,7 @@ AppView = Backbone.View.extend $("i.fa",el).attr("class","fa fa-thumbs-up") initCabe: () -> - @cable = ActionCable.createConsumer("/cable") - @notification = @cable.subscriptions.create "NotificationChannel", + @notification = App.cable.subscriptions.create "NotificationsChannel", received: (data) => @receivedNotificationCount(data) @@ -221,6 +220,7 @@ window.App = access_token : '' asset_url : '' root_url : '' + cable: ActionCable.createConsumer("/cable") isLogined : -> App.current_user_id != null diff --git a/app/assets/javascripts/topics.coffee b/app/assets/javascripts/topics.coffee index fa5b11f777..6178241378 100644 --- a/app/assets/javascripts/topics.coffee +++ b/app/assets/javascripts/topics.coffee @@ -1,10 +1,12 @@ # TopicsController 下所有页面的 JS 功能 window.Topics = + topic_id: null user_liked_reply_ids: [] window.TopicView = Backbone.View.extend el: "body" currentPageImageURLs : [] + clearHightTimer: null events: "click #replies .reply .btn-reply": "reply" @@ -15,15 +17,24 @@ window.TopicView = Backbone.View.extend "click a.follow": "follow" "click a.bookmark": "bookmark" "click .btn-move-page": "scrollPage" + "click .notify-updated .update": "updateReplies" initialize: (opts) -> @parentView = opts.parentView @initComponents() + @initCableUpdate() @initDropzone() @initContentImageZoom() @initCloseWarning() @checkRepliesLikeStatus() + @resetClearReplyHightTimer() + + resetClearReplyHightTimer: -> + clearTimeout(@clearHightTimer) + @clearHightTimer = setTimeout -> + $(".reply").removeClass("light") + , 10000 initDropzone: -> @@ -187,6 +198,7 @@ window.TopicView = Backbone.View.extend # Ajax 回复后的事件 replyCallback : (success, msg) -> + return if msg == '' $("#main .alert-message").remove() if success $("abbr.timeago",$("#replies .reply").last()).timeago() @@ -198,6 +210,7 @@ window.TopicView = Backbone.View.extend App.alert(msg,'#reply') $("#new_reply textarea").focus() $('#reply-button').button('reset') + @resetClearReplyHightTimer() # 图片点击增加全屏预览功能 initContentImageZoom : () -> @@ -379,3 +392,20 @@ window.TopicView = Backbone.View.extend # Focus title field in new-topic page $("body[data-controller-name='topics'] #topic_title").focus() + + initCableUpdate: () -> + params = + channel: 'RepliesChannel' + topic_id: Topics.topic_id + App.cable.subscriptions.create params, + received: (json) => + if json.user_id == App.current_user_id + return false + if json.action == 'create' + $(".notify-updated").show() + + updateReplies: () -> + lastId = $("#replies .reply:last").data('id') + $.get "/topics/#{Topics.topic_id}/replies.js?last_id=#{lastId}", -> + $(".notify-updated").hide() + false diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index bed0b90b93..306a3d85da 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -953,5 +953,15 @@ footer { } } +.notify-updated { + display: none; + padding: 4px 15px; + margin-bottom: 20px; + text-align: left; + background: #FDF8A6; border:1px solid #F5E3A4; color: $redLabelText; + a:link, + a:visited { color: $yellowText; } +} + .dz-preview { display: none; } textarea.div-dropzone-focus { border-color: #BBE1C9; background: #fafafa; } diff --git a/app/channels/notification_channel.rb b/app/channels/notifications_channel.rb similarity index 66% rename from app/channels/notification_channel.rb rename to app/channels/notifications_channel.rb index 93d3981c92..1fbcb85737 100644 --- a/app/channels/notification_channel.rb +++ b/app/channels/notifications_channel.rb @@ -1,4 +1,4 @@ -class NotificationChannel < ApplicationCable::Channel +class NotificationsChannel < ApplicationCable::Channel def subscribed stream_from "notifications_count/#{current_user.id}" end diff --git a/app/channels/replies_channel.rb b/app/channels/replies_channel.rb new file mode 100644 index 0000000000..33eff30ea0 --- /dev/null +++ b/app/channels/replies_channel.rb @@ -0,0 +1,8 @@ +class RepliesChannel < ApplicationCable::Channel + def subscribed + stream_from "topics/#{params[:topic_id]}/replies" + end + + def unsubscribed + end +end diff --git a/app/controllers/replies_controller.rb b/app/controllers/replies_controller.rb index 85d2867298..fc3d0be731 100644 --- a/app/controllers/replies_controller.rb +++ b/app/controllers/replies_controller.rb @@ -17,6 +17,13 @@ def create end end + def index + @replies = Reply.unscoped.where("topic_id = ? and id > ?", @topic.id, params[:last_id]).without_body.order(:id).all + end + + def show + end + def edit @reply = Reply.find(params[:id]) end diff --git a/app/models/reply.rb b/app/models/reply.rb index 53b02d10e0..a63ad26487 100644 --- a/app/models/reply.rb +++ b/app/models/reply.rb @@ -82,9 +82,15 @@ def self.notify_reply_created(reply_id) end end + self.broadcast_to_client(reply) + true end + def self.broadcast_to_client(reply) + ActionCable.server.broadcast "topics/#{reply.topic_id}/replies", { id: reply.id, user_id: reply.user_id, action: :create } + end + # 是否热门 def popular? likes_count >= 5 diff --git a/app/views/replies/_create_callback.js.erb b/app/views/replies/_create_callback.js.erb new file mode 100644 index 0000000000..eececfdea1 --- /dev/null +++ b/app/views/replies/_create_callback.js.erb @@ -0,0 +1,17 @@ +if($("#replies").length == 0){ + Turbolinks.visit(location.href); +} else { + if ($(".reply[data-id=<%= reply.id %>]").length == 0) { + var current_floor = parseInt($("#replies").data("last-floor")) + 1; + var dom = $('<%= j(render("reply", reply: reply, reply_counter: @topic.replies_count - 1, display_edit: true)) %>'); + $("#replies .items").append(dom); + $("#replies .total b").text('<%= @replies_count %>'); + $('#topic-sidebar .total b').text('<%= @replies_count %>'); + dom.find(".reply-floor").text(current_floor + " 楼"); + dom.find("a.edit").css("display", "inline-block"); + dom.addClass('light'); + $("#replies").data("last-floor", current_floor); + _topicView.resetClearReplyHightTimer(); + } +} + diff --git a/app/views/replies/_reply.html.erb b/app/views/replies/_reply.html.erb index 06caadb62b..aeeeef915b 100644 --- a/app/views/replies/_reply.html.erb +++ b/app/views/replies/_reply.html.erb @@ -2,7 +2,7 @@ <% floor = reply_counter + 1 %> -
+
<% if reply.deleted? and !@show_raw %>
<%= floor %><%= t("common.floor")%> <%= t("common.deleted")%>
<% else %> diff --git a/app/views/replies/create.js.erb b/app/views/replies/create.js.erb index 6b38aa2e4a..5c4288baf0 100644 --- a/app/views/replies/create.js.erb +++ b/app/views/replies/create.js.erb @@ -1,22 +1,11 @@ -<% if @reply.errors.blank? %> +<% if !@reply.errors.blank? %> + _topicView.replyCallback(0, '<%= j(@msg) %>'); +<% else %> <% if @reply.upvote? %> Turbolinks.visit(location.href); <% else %> - <% @page = 1 %> - if($("#replies").length == 0){ - Turbolinks.visit(location.href); - } - else { - var current_floor = parseInt($("#replies").data("last-floor")) + 1; - $("#replies .items").append('<%= j(render("reply", reply: @reply, reply_counter: @topic.replies_count - 1, display_edit: true)) %>') - $("#replies .items .reply:last .reply-floor").text(current_floor + " 楼"); - $("#replies").data("last-floor", current_floor); - $("#replies .reply a.edit:last").css("display", "inline-block"); - $("#replies .total b").text('<%= @replies_count %>'); - $('#topic-sidebar .total b').text('<%= @replies_count %>'); - _topicView.replyCallback(1, '<%= j(@msg) %>'); - } + <%= render 'create_callback', reply: @reply %> + + _topicView.replyCallback(1, '<%= j(@msg) %>'); <% end %> -<% else %> - _topicView.replyCallback(0, '<%= j(@msg) %>'); <% end %> diff --git a/app/views/replies/index.js.erb b/app/views/replies/index.js.erb new file mode 100644 index 0000000000..0f79b051c5 --- /dev/null +++ b/app/views/replies/index.js.erb @@ -0,0 +1,3 @@ +<% @replies.each do |reply| %> + <%= render 'create_callback', reply: reply %> +<% end %> diff --git a/app/views/topics/show.html.erb b/app/views/topics/show.html.erb index dac643e4a4..ab6ddd8896 100644 --- a/app/views/topics/show.html.erb +++ b/app/views/topics/show.html.erb @@ -1,5 +1,6 @@ <% content_for :scripts do %>