I recently upgraded from Rails 6.1.4.6 to 7.0.2.2. With this upgrade I switched from webpacker to import maps with sprockets. My repo didn’t include turbolinks or stimulus and I didn’t feel like adding them now either. So I re-added UJS and most of my tests pass except the action cable feature tests. It seems I cannot get action cable to connect.
Any help would be appreciated!
Gemfile
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby "3.0.2"
# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
gem "rails", "~> 7.0", ">= 7.0.2.2"
# The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
gem "sprockets-rails", "~> 3.4.2"
# Use postgresql as the database for Active Record
gem "pg", "~> 1.1"
# Use the Puma web server [https://github.com/puma/puma]
gem "puma", "~> 5.0"
# Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]
gem "importmap-rails", "~> 1.0"
# Build JSON APIs with ease [https://github.com/rails/jbuilder]
gem "jbuilder", "~> 2.0"
# Use Redis adapter to run Action Cable in production
gem "redis", "~> 4.0"
# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword]
gem "bcrypt", "~> 3.1.7"
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ]
# Reduces boot times through caching; required in config/boot.rb
gem "bootsnap", require: false
# Use SCSS for stylesheets
gem "sassc-rails", "~> 2.1.2"
# FontAwesome icons for sprockets and SASS
gem "font-awesome-sass", "~> 5.15.1"
# Payment management system
gem "stripe", "~> 5.45.0"
# Email management system
gem "sendgrid-ruby", "~> 6.6.1"
# Communications (voice/sms) system
gem "twilio-ruby", "~> 5.65.0"
# HTTP request gem
gem "faraday", "~> 1.10.0"
# Enable cross-origin AJAX
gem "rack-cors", "~> 1.1.1"
# Authentication framework
gem "devise", "~> 4.8.0"
# Efficient SQL importer
gem "activerecord-import", "~> 1.3.0"
# Session store backed by an Active Record class
gem "activerecord-session_store", "~> 2.0.0"
# Production background worker
gem "sidekiq", "~> 6.4.0"
# Extention for sidekiq cron jobs
gem "sidekiq-scheduler", "~> 3.1.1"
# Segment Analytics Gem
gem "analytics-ruby", "~> 2.4.0"
group :development, :test do
# Debugging tool
gem "pry", "~> 0.14.1"
# Testing framework
gem "rspec-rails", "~> 5.0.0"
# Broswer webdriver for testing
gem "selenium-webdriver", "~> 3.142", ">= 3.142.7"
end
group :development do
# Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler]
gem "rack-mini-profiler", "~> 2.0"
# Use console on exceptions pages [https://github.com/rails/web-console]
gem "web-console", "~> 4.2.0"
# Linter
gem "rubocop-rails", require: false
end
group :test do
# Testing frontend integration
gem "capybara", "~> 3.36.0"
# Testing coverage
gem "simplecov", "~> 0.21.2", require: false
# Disallow API calls during testing
gem "webmock", "~> 3.14.0"
# Make initial API call and save as fixtures
gem "vcr", "~> 6.0.0"
# Generate fixtures for testing
gem "factory_bot_rails", "~> 6.2.0"
gem "faker", "~> 2.19.0"
end
config/cable.yml
development:
adapter: async
test:
adapter: test
production:
adapter: redis
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
channel_prefix: my_app_name
config/routes.rb
mount ActionCable.server => "/cable"
config/importmaps.rb
pin "application", preload: true
pin "@rails/actioncable", to: "actioncable.esm.js"
pin_all_from "app/javascript/channels", under: "channels"
app/assets/config/manifest.js
//= link_tree ../images
//= link_directory ../stylesheets .scss
//= link_tree ../javascript .js
//= link_tree ../../../vendor/javascript .js
//= link application.css
//= link channels/consumer.js
//= link channels/index.js
//= link channels/messages_channel.js
app/javascripts/application.js
import "@rails/actioncable"
import "channels"
app/javascripts/channels/index.js
import "channels/market_channel"
import "channels/messages_channel"
app/javascripts/channels/consumer.js
import { createConsumer } from "@rails/actioncable"
export default createConsumer()
app/javascripts/channels/messages_channel.js
import consumer from "channels/consumer"
consumer.subscriptions.create("MessagesChannel", {
connected() {
console.log('connected');
},
disconnected() {
// Called when the subscription has been terminated by the server
},
received(data) {
... js code ...
}
});
Log showing connection to /cable
Started GET "/cable" for ::1 at 2022-03-09 08:58:22 -0700
Started GET "/cable/" [WebSocket] for ::1 at 2022-03-09 08:58:22 -0700
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 2], ["LIMIT", 1]]
↳ app/channels/application_cable/connection.rb:14:in `find_verified_user'
Registered connection (Z2lkOi8vY2FsZW5kYXJpemUvVXNlci8y)
MessagesChannel is transmitting the subscription confirmation
MessagesChannel is streaming from messages:2
MarketChannel is transmitting the subscription confirmation
MarketChannel is streaming from market_channel
2
Answers
Figured out the problem was because I had two
applications.js
files. One inapp/assets/javascripts/
and another inapp/javascript
. Sprockets was serving my asset version of application.js due to my manifest pointing there. I adjusted the manifest and deleted the secondary application.js and all is working.I had simirlar Error !
My Error was :
It was caused in
app/javascript/channels/index.js
The solution was really simple which was adding channels to the import in
app/javascript/channels/index.js
My manifest.js looks like :