diff --git a/Gemfile b/Gemfile
index 0dcecef..33b625a 100644
--- a/Gemfile
+++ b/Gemfile
@@ -18,6 +18,9 @@ gem 'redis', '~> 4.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
+# Efficient ActionCable replacement to use web-sockets
+gem 'anycable-rails', '~> 0.6', github: "anycable/anycable-rails", branch: "feature/rack-middleware"
+
# Use ActiveStorage variant
# gem 'mini_magick', '~> 4.8'
diff --git a/Gemfile.lock b/Gemfile.lock
index 68490b6..984f58b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,3 +1,12 @@
+GIT
+ remote: https://github.com/anycable/anycable-rails.git
+ revision: 59ebcbf9033725637b08dee5cbd5e26891dfc354
+ branch: feature/rack-middleware
+ specs:
+ anycable-rails (0.6.4)
+ anycable (~> 0.6.0)
+ rails (>= 5)
+
GEM
remote: https://rubygems.org/
specs:
@@ -42,6 +51,10 @@ GEM
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
+ anycable (0.6.3)
+ anyway_config (~> 1.4.2)
+ grpc (~> 1.17)
+ anyway_config (1.4.4)
arel (9.0.0)
bindex (0.8.1)
bootsnap (1.4.4)
@@ -55,6 +68,12 @@ GEM
ffi (1.11.1)
globalid (0.4.2)
activesupport (>= 4.2.0)
+ google-protobuf (3.10.1)
+ googleapis-common-protos-types (1.0.4)
+ google-protobuf (~> 3.0)
+ grpc (1.25.0)
+ google-protobuf (~> 3.8)
+ googleapis-common-protos-types (~> 1.0)
i18n (1.6.0)
concurrent-ruby (~> 1.0)
jbuilder (2.9.1)
@@ -153,6 +172,7 @@ PLATFORMS
ruby
DEPENDENCIES
+ anycable-rails (~> 0.6)!
bootsnap (>= 1.1.0)
byebug
jbuilder (~> 2.5)
diff --git a/Procfile b/Procfile
index 8f60e2a..4a649d8 100644
--- a/Procfile
+++ b/Procfile
@@ -1 +1,2 @@
-server: bin/rails server
+web: bin/heroku-web
+release: bundle exec rails db:migrate
diff --git a/Procfile.dev b/Procfile.dev
index ca3bc6b..432a2fd 100644
--- a/Procfile.dev
+++ b/Procfile.dev
@@ -1,2 +1,3 @@
server: bin/rails server
assets: bin/webpack-dev-server
+anycable: bundle exec anycable --server-command "anycable-go --port 3334"
diff --git a/README.md b/README.md
index cb2e17f..81629e3 100644
--- a/README.md
+++ b/README.md
@@ -16,16 +16,26 @@ If you are looking for code that reflects application at the end of any part, ta
- [part-2 branch](https://github.com/demiazz/evil_chat/tree/part-2) for the Part 2;
- [part-3 branch](https://github.com/demiazz/evil_chat/tree/part-3) for the Part 3.
-# Installation
+# Development installation
+## When using localhost machine
+
+```sh
+cp config/database.yml.example config/database.yml
+
+bundle install
+bin/rails db:migrate
+yarn install
+brew install hivemind
+brew install anycable-go
+hivemind Procfile.dev
```
-$ cp config/database.yml.example config/database.yml
-$ bin/rails credentials:edit
+## When using Docker Compose
-$ bundle install
-$ bin/rails db:migrate
-$ yarn install
-$ brew install hivemind
-$ hivemind Procfile.dev
+```sh
+brew install bibendi/dip/dip
+eval "$(dip console)"
+provision
+rails s
```
diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb
index dde95a7..181bb61 100644
--- a/app/channels/application_cable/connection.rb
+++ b/app/channels/application_cable/connection.rb
@@ -3,7 +3,7 @@ class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
- self.current_user = request.session.fetch("username", nil)
+ self.current_user = session.fetch("username", nil)
reject_unauthorized_connection unless current_user
end
end
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 839f820..2f9c6da 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -4,6 +4,7 @@
EvilChat
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
+ <%= action_cable_meta_tag %>
<%= stylesheet_pack_tag 'application', media: 'all' %>
diff --git a/bin/heroku-web b/bin/heroku-web
new file mode 100755
index 0000000..7d5b6a3
--- /dev/null
+++ b/bin/heroku-web
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+if [ "$ANYCABLE_DEPLOYMENT" == "true" ]; then
+ bundle exec anycable --server-command="anycable-go"
+else
+ bundle exec rails server -p $PORT -b 0.0.0.0
+fi
diff --git a/config/anycable.yml b/config/anycable.yml
new file mode 100644
index 0000000..f8d54a0
--- /dev/null
+++ b/config/anycable.yml
@@ -0,0 +1,30 @@
+# This file contains per-environment settings for AnyCable.
+#
+# Since AnyCable config is based on anyway_config (https://github.com/palkan/anyway_config), all AnyCable settings
+# can be set or overridden through the corresponding environment variables.
+# E.g., `rpc_host` is overridden by ANYCABLE_RPC_HOST, `debug` by ANYCABLE_DEBUG etc.
+#
+# Note that AnyCable recognizes REDIS_URL env variable for Redis pub/sub adapter. If you want to
+# use another Redis instance for AnyCable, provide ANYCABLE_REDIS_URL variable.
+#
+# Read more about AnyCable configuration here: https://docs.anycable.io/#/ruby/configuration
+#
+default: &default
+ # Turn on/off access logs ("Started..." and "Finished...")
+ access_logs_disabled: false
+ # This is the host and the port to run AnyCable RPC server on.
+ # You must configure your WebSocket server to connect to it, e.g.:
+ # $ anycable-go --rpc-host=":50051"
+ rpc_host: "127.0.0.1:50051"
+ # Whether to enable gRPC level logging or not
+ log_grpc: false
+ # Use the same channel name for WebSocket server, e.g.:
+ # $ anycable-go --redis-channel="__anycable__"
+ redis_channel: "__anycable__"
+
+development:
+ <<: *default
+ redis_url: "redis://localhost:6379/1"
+
+production:
+ <<: *default
diff --git a/config/cable.yml b/config/cable.yml
index 1876ed7..8a279ad 100644
--- a/config/cable.yml
+++ b/config/cable.yml
@@ -1,10 +1,11 @@
+# Make it possible to switch adapters by passing the CABLE_ADAPTER env variable.
+# For example, you can use it fallback to the standard Action Cable in staging/review
+# environments (by setting `CABLE_ADAPTER=redis`).
development:
- adapter: async
+ adapter: <%= ENV.fetch("CABLE_ADAPTER", "any_cable") %>
test:
- adapter: async
+ adapter: test
production:
- adapter: redis
- url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
- channel_prefix: evil_chat_production
+ adapter: <%= ENV.fetch("CABLE_ADAPTER", "any_cable") %>
diff --git a/config/environments/development.rb b/config/environments/development.rb
index d52ec9e..9407425 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
@@ -51,4 +53,7 @@
# 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
+
+ # Specify AnyCable WebSocket server URL to use by JS client
+ config.action_cable.url = ENV.fetch("CABLE_URL", "ws://localhost:3334/cable").presence
end
diff --git a/config/environments/production.rb b/config/environments/production.rb
index 6026643..d0bdb2d 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
@@ -16,7 +18,7 @@
# Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
# or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
- config.require_master_key = true
+ # config.require_master_key = true
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
@@ -35,6 +37,8 @@
# Mount Action Cable outside main process or domain
# config.action_cable.mount_path = nil
# config.action_cable.url = 'wss://example.com/cable'
+ # Specify AnyCable WebSocket server URL to use by JS client
+ config.action_cable.url = ENV["CABLE_URL"].presence
# 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.
diff --git a/config/master.key.back b/config/master.key.back
deleted file mode 100644
index 8b63c1e..0000000
--- a/config/master.key.back
+++ /dev/null
@@ -1 +0,0 @@
-533269e346eb9fd9dc4adc9807749c03
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
index 09fde98..ee98a08 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -34,7 +34,9 @@ services:
EDITOR: vim
RAILS_ENV: ${RAILS_ENV:-development}
DATABASE_URL: postgres://postgres:postgres@postgres:5432
- REDIS_URL: redis://redis:6379/
+ REDIS_URL: redis://redis:6379/0
+ ANYCABLE_REDIS_URL: redis://redis:6379/0
+ ANYCABLE_RPC_HOST: 0.0.0.0:50051
WEBPACKER_DEV_SERVER_HOST: webpacker
DISABLE_SPRING: 1
depends_on:
@@ -55,6 +57,10 @@ services:
condition: service_healthy
webpacker:
condition: service_started
+ anycable-ws:
+ condition: service_started
+ anycable-rpc:
+ condition: service_started
webpacker:
<<: *app
@@ -69,6 +75,24 @@ services:
RAILS_ENV: ${RAILS_ENV:-development}
WEBPACKER_DEV_SERVER_HOST: 0.0.0.0
+ anycable-ws:
+ image: anycable/anycable-go:v0.6.4
+ ports:
+ - '3334:3334'
+ environment:
+ PORT: 3334
+ ANYCABLE_REDIS_URL: redis://redis:6379/0
+ ANYCABLE_RPC_HOST: anycable-rpc:50051
+ depends_on:
+ - anycable-rpc
+ - redis
+
+ anycable-rpc:
+ <<: *backend
+ command: bundle exec anycable
+ ports:
+ - '50051'
+
postgres:
image: postgres:12
volumes: