Class: Solrengine::Sdp::InstallGenerator

Inherits:
Rails::Generators::Base
  • Object
show all
Defined in:
lib/generators/solrengine/sdp/install_generator.rb

Overview

‘bin/rails generate solrengine:sdp:install`

One run gives a default Rails app everything Wallet-per-User needs:

* two timestamped migrations (WalletOwner columns on users + the
  solrengine_sdp_transfers table) — skipped when a migration of the
  same name already exists, so re-running never duplicates them
* config/initializers/solrengine_sdp.rb (ENV-backed configuration)
* `include Solrengine::Sdp::WalletOwner` injected into app/models/user.rb
* bin/sdp_watcher + a Procfile.dev entry for it
* SDP_* keys appended to .env
* a working development cable adapter (see #configure_cable_adapter —
  the default async adapter silently drops the watcher's broadcasts)

Constant Summary collapse

MIGRATIONS =
%w[add_solrengine_sdp_to_users create_solrengine_sdp_transfers].freeze
ASYNC_DEVELOPMENT_BLOCK =

The exact development block ‘rails new` emits — the only async config this generator rewrites mechanically. Anything else async-but-custom gets loud manual instructions instead of risky surgery.

"development:\n  adapter: async\n"
SOLID_CABLE_DEVELOPMENT_BLOCK =
<<~YAML
  development:
    adapter: solid_cable
    polling_interval: 0.1.seconds
    message_retention: 1.hour
YAML

Instance Method Summary collapse

Instance Method Details

#append_env_keysObject



88
89
90
91
92
93
94
95
96
# File 'lib/generators/solrengine/sdp/install_generator.rb', line 88

def append_env_keys
  return if exists?(".env") && read(".env").include?("SDP_API_KEY")

  if exists?(".env")
    append_to_file ".env", env_block
  else
    create_file ".env", env_block
  end
end

#configure_cable_adapterObject

The cable adapter is part of this engine’s correctness, not a nicety: the default ‘async` adapter accepts broadcasts but delivers them in-process only, so everything bin/sdp_watcher (a separate process) pushes would be silently dropped — no error, the browser just never updates. Development must be on a cross-process adapter.

Decision (documented): the meta-gem’s surgery force-replaces database.yml with its own multi-database layout; this generator stays single-database and writes a solid_cable development block WITHOUT connects_to (Solid Cable then uses the primary database) plus loud instructions for the gem + table. bin/sdp_watcher proves the result with a boot-time broadcast self-check.



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/generators/solrengine/sdp/install_generator.rb', line 110

def configure_cable_adapter
  unless exists?("config/cable.yml")
    copy_file "cable.yml", "config/cable.yml"
    say_cable_instructions
    return
  end

  adapter = development_cable_adapter
  if adapter == "async"
    if read("config/cable.yml").include?(ASYNC_DEVELOPMENT_BLOCK)
      gsub_file "config/cable.yml", ASYNC_DEVELOPMENT_BLOCK, SOLID_CABLE_DEVELOPMENT_BLOCK
      say_cable_instructions
    else
      say_cable_refusal("development uses the async adapter in a non-default layout")
    end
  elsif adapter.is_a?(String) && !adapter.empty?
    say_status :identical, "config/cable.yml development adapter is #{adapter} — cable adapter OK", :blue
  else
    say_cable_refusal("could not determine the development adapter")
  end
end

#create_initializerObject



51
52
53
# File 'lib/generators/solrengine/sdp/install_generator.rb', line 51

def create_initializer
  copy_file "initializer.rb", "config/initializers/solrengine_sdp.rb"
end

#create_migrationsObject



37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/generators/solrengine/sdp/install_generator.rb', line 37

def create_migrations
  base = Time.now.utc
  MIGRATIONS.each_with_index do |name, offset|
    if migration_exists?(name)
      say_status :skip, "db/migrate/*_#{name}.rb already exists", :yellow
      next
    end

    # +offset keeps the two versions unique within a single run.
    version = (base + offset).strftime("%Y%m%d%H%M%S")
    copy_file "#{name}.rb", "db/migrate/#{version}_#{name}.rb"
  end
end

#include_wallet_owner_in_user_modelObject



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/generators/solrengine/sdp/install_generator.rb', line 55

def include_wallet_owner_in_user_model
  user_model = "app/models/user.rb"
  unless exists?(user_model)
    say_status :skip, "#{user_model} not found — add `include Solrengine::Sdp::WalletOwner` " \
      "to your wallet-owner model and point config.user_class at it", :yellow
    return
  end
  return if read(user_model).include?("Solrengine::Sdp::WalletOwner")

  inject_into_class user_model, "User", <<-RUBY
  include Solrengine::Sdp::WalletOwner

  # Provision a custody wallet on signup (opt-in — uncomment to enable):
  # after_create_commit :provision_wallet!

  RUBY
end

#install_watcherObject



73
74
75
76
# File 'lib/generators/solrengine/sdp/install_generator.rb', line 73

def install_watcher
  copy_file "sdp_watcher", "bin/sdp_watcher"
  chmod "bin/sdp_watcher", 0o755
end

#show_post_installObject



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/generators/solrengine/sdp/install_generator.rb', line 132

def show_post_install
  say "\n  solrengine-sdp installed!", :green
  say <<~MSG

      Next steps:
        1. bin/rails db:migrate
        2. Fill in .env: SDP_API_KEY (needs custody:admin + wallets:* + payments:* scopes),
           SDP_API_BASE_URL, SDP_CUSTODY_PROVIDER
        3. Wallet-per-User needs a MANAGED custody provider (e.g. Privy) and Kora for
           transfer execution — see the solrengine-sdp README "Prerequisites"
        4. To provision wallets on signup, uncomment in app/models/user.rb:
             after_create_commit :provision_wallet!
        5. bin/dev — Procfile.dev now runs bin/sdp_watcher alongside the web server

  MSG
end

#update_procfileObject



78
79
80
81
82
83
84
85
86
# File 'lib/generators/solrengine/sdp/install_generator.rb', line 78

def update_procfile
  if exists?("Procfile.dev")
    unless read("Procfile.dev").include?("sdp_watcher:")
      append_to_file "Procfile.dev", "sdp_watcher: bin/sdp_watcher\n"
    end
  else
    create_file "Procfile.dev", "web: bin/rails server\nsdp_watcher: bin/sdp_watcher\n"
  end
end