class AnyCableRailsGenerators::SetupGenerator

Entry point for interactive installation

Constants

DEVELOPMENT_METHODS
DOCS_ROOT
SERVER_SOURCES

Public Instance Methods

cable_url() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 48
    def cable_url
      environment(nil, env: :development) do
        <<~SNIPPET
          # Specify AnyCable WebSocket server URL to use by JS client
          config.after_initialize do
            config.action_cable.url = ActionCable.server.config.url = ENV.fetch("CABLE_URL", "ws://localhost:8080/cable") if AnyCable::Rails.enabled?
          end
        SNIPPET
      end

      environment(nil, env: :production) do
        <<~SNIPPET
          # Specify AnyCable WebSocket server URL to use by JS client
          config.after_initialize do
            config.action_cable.url = ActionCable.server.config.url = ENV.fetch("CABLE_URL") if AnyCable::Rails.enabled?
          end
        SNIPPET
      end

      say_status :info, "✅ 'config.action_cable.url' has been configured"
      say_status :help, "⚠️  If you're using JS client make sure you have " \
                        "`action_cable_meta_tag` included before any <script> tag in your application.html"
    end
configs() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 41
def configs
  inside("config") do
    template "cable.yml"
    template "anycable.yml"
  end
end
development_method() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 72
def development_method
  answer = DEVELOPMENT_METHODS.index(options[:devenv]) || 99

  until DEVELOPMENT_METHODS[answer.to_i]
    answer = ask "Which environment do you use for development? (1) Local, (2) Docker, (0) Skip"
  end

  case env = DEVELOPMENT_METHODS[answer.to_i]
  when "skip"
    say_status :help, "⚠️  Please, read this guide on how to install AnyCable-Go server 👉 #{DOCS_ROOT}/anycable-go/getting_started", :yellow
  else
    send "install_for_#{env}"
  end
end
devise() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 106
def devise
  in_root do
    return unless File.file?("config/initializers/devise.rb")
  end

  inside("config/initializers") do
    template "anycable.rb"
  end

  say_status :info, "✅ config/initializers/anycable.rb with Devise configuration has been added"
end
finish() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 132
def finish
  say_status :info, "✅ AnyCable has been configured successfully!"
end
heroku() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 87
def heroku
  if options[:skip_heroku].nil?
    return unless yes? "Do you use Heroku for deployment? [Yn]"
  elsif options[:skip_heroku]
    return
  end

  in_root do
    next unless File.file?("Procfile")

    contents = File.read("Procfile")
    contents.sub!(/^web: (.*)$/, %q(web: [[ "$ANYCABLE_DEPLOYMENT" == "true" ]] && bundle exec anycable --server-command="anycable-go" || \1))
    File.write("Procfile", contents)
    say_status :info, "✅ Procfile updated"
  end

  say_status :help, "️️⚠️  Please, read the required steps to configure Heroku applications 👉 #{DOCS_ROOT}/deployment/heroku", :yellow
end
rubocop_compatibility() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 124
def rubocop_compatibility
  return unless rubocop?

  say_status :info, "🤖 Running static compatibility checks with RuboCop"
  res = run "bundle exec rubocop -r 'anycable/rails/compatibility/rubocop' --only AnyCable/InstanceVars,AnyCable/PeriodicalTimers,AnyCable/InstanceVars"
  say_status :help, "⚠️  Please, take a look at the icompatibilities above and fix them. See #{DOCS_ROOT}/rails/compatibility" unless res
end
stimulus_reflex() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 118
def stimulus_reflex
  return unless stimulus_reflex?

  say_status :help, "⚠️  Please, check out the documentation on using AnyCable with Stimulus Reflex: #{DOCS_ROOT}/rails/stimulus_reflex"
end
welcome() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 37
def welcome
  say "👋 Welcome to AnyCable interactive installer."
end

Private Instance Methods

anycable_go_options() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 270
def anycable_go_options
  redis? ? " --port=8080" : " --port=8080 --broadcast_adapter=http"
end
download_options(**params) click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 260
def download_options(**params)
  opts = options.merge(params)
  [].tap do |args|
    args << "--os #{opts[:os]}" if opts[:os]
    args << "--cpu #{opts[:cpu]}" if opts[:cpu]
    args << "--bin-path=#{opts[:bin_path]}" if opts[:bin_path]
    args << "--version #{opts[:version]}" if opts[:version]
  end.join(" ")
end
file_exists?(name) click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 274
def file_exists?(name)
  in_root do
    return File.file?(name)
  end
end
gemfile_lock() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 154
def gemfile_lock
  @gemfile_lock ||= begin
    res = nil
    in_root do
      next unless File.file?("Gemfile.lock")
      res = File.read("Gemfile.lock")
    end
    res
  end
end
install_for_docker() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 165
    def install_for_docker
      # Remove localhost from configuraiton
      gsub_file "config/anycable.yml", /^.*redis_url:.*localhost[^\n]+\n/, ""

      say_status :help, "️️⚠️  Docker development configuration could vary", :yellow

      say "Here is an example snippet for docker-compose.yml:"
      say <<~YML
        ─────────────────────────────────────────
        ws:
          image: anycable/anycable-go:1.0
          ports:
            - '8080:8080'
          environment:
            ANYCABLE_HOST: "0.0.0.0"
            ANYCABLE_REDIS_URL: redis://redis:6379/0
            ANYCABLE_RPC_HOST: anycable:50051
            ANYCABLE_DEBUG: 1
          depends_on:
            redis:
              condition: service_healthy

        anycable:
          <<: *backend
          command: bundle exec anycable
          environment:
            <<: *backend_environment
            ANYCABLE_REDIS_URL: redis://redis:6379/0
            ANYCABLE_RPC_HOST: 0.0.0.0:50051
            ANYCABLE_DEBUG: 1
          ports:
            - '50051'
          depends_on:
            <<: *backend_depends_on
            ws:
              condition: service_started
        ─────────────────────────────────────────
      YML
    end
install_for_local() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 205
def install_for_local
  install_server
  template_proc_files
end
install_from_binary() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 251
def install_from_binary
  bin_path ||= DEFAULT_BIN_PATH if options[:devenv] # User don't want interactive mode
  bin_path ||= ask "Please, enter the path to download the AnyCable-Go binary to", default: DEFAULT_BIN_PATH, path: true

  generate "anycable:download", download_options(bin_path: bin_path)

  true
end
install_from_brew() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 246
def install_from_brew
  run "brew install anycable-go", abort_on_failure: true
  run "anycable-go -v", abort_on_failure: true
end
install_server() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 210
def install_server
  answer = SERVER_SOURCES.index(options[:source]) || 99

  until SERVER_SOURCES[answer.to_i]
    answer = ask "How do you want to install AnyCable-Go WebSocket server? (1) Homebrew, (2) Download binary, (0) Skip"
  end

  case answer.to_i
  when 0
    say_status :help, "⚠️  Please, read this guide on how to install AnyCable-Go server 👉 #{DOCS_ROOT}/anycable-go/getting_started", :yellow
    return
  else
    return unless send("install_from_#{SERVER_SOURCES[answer.to_i]}")
  end

  say_status :info, "✅ AnyCable-Go WebSocket server has been successfully installed"
end
redis?() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 142
def redis?
  !!gemfile_lock&.match?(/^\s+redis\b/)
end
rubocop?() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 150
def rubocop?
  !!gemfile_lock&.match?(/^\s+rubocop\b/)
end
stimulus_reflex?() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 138
def stimulus_reflex?
  !!gemfile_lock&.match?(/^\s+stimulus_reflex\b/)
end
template_proc_files() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 228
def template_proc_files
  file_name = "Procfile.dev"

  if file_exists?(file_name)
    append_file file_name, "anycable: bundle exec anycable\nws: anycable-go#{anycable_go_options}", force: true
  else
    say_status :help, "💡 We recommend using Hivemind to manage multiple processes in development 👉 https://github.com/DarthSim/hivemind", :yellow

    if options[:skip_procfile_dev].nil?
      return unless yes? "Do you want to create a '#{file_name}' file?"
    elsif options[:skip_procfile_dev]
      return
    end

    template file_name
  end
end
webpacker?() click to toggle source
# File lib/generators/anycable/setup/setup_generator.rb, line 146
def webpacker?
  !!gemfile_lock&.match?(/^\s+webpacker\b/)
end