Class: TemporaryDb

Inherits:
Object
  • Object
show all
Defined in:
lib/temporary_db.rb

Constant Summary collapse

PG_TEMP_PATH =
"/tmp/pg_schema_tmp"
PG_CONF =
"#{PG_TEMP_PATH}/postgresql.conf"
PG_SOCK_PATH =
"#{PG_TEMP_PATH}/sockets"

Instance Method Summary collapse

Instance Method Details

#find_free_port(range) ⇒ Object



45
46
47
# File 'lib/temporary_db.rb', line 45

def find_free_port(range)
  range.each { |port| return port if port_available?(port) }
end

#initdb_pathObject



36
37
38
39
40
41
42
43
# File 'lib/temporary_db.rb', line 36

def initdb_path
  return @initdb_path if @initdb_path

  @initdb_path = `which initdb 2> /dev/null`.strip
  @initdb_path = "#{pg_bin_path}/initdb" if @initdb_path.length == 0

  @initdb_path
end

#migrateObject



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/temporary_db.rb', line 117

def migrate
  raise "Error: the database must be started before it can be migrated." if !@started
  ActiveRecord::Base.establish_connection(
    adapter: "postgresql",
    database: "discourse",
    port: pg_port,
    host: "localhost",
  )

  puts "Running migrations on blank database!"

  old_stdout = $stdout.clone
  old_stderr = $stderr.clone
  $stdout.reopen(File.new("/dev/null", "w"))
  $stderr.reopen(File.new("/dev/null", "w"))

  SeedFu.quiet = true
  Rake::Task["db:migrate"].invoke
ensure
  $stdout.reopen(old_stdout) if old_stdout
  $stderr.reopen(old_stderr) if old_stderr
end

#pg_bin_pathObject



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/temporary_db.rb', line 15

def pg_bin_path
  return @pg_bin_path if @pg_bin_path

  %w[13 12 11 10].each do |v|
    bin_path = "/usr/lib/postgresql/#{v}/bin"
    if File.exist?("#{bin_path}/pg_ctl")
      @pg_bin_path = bin_path
      break
    end
  end
  if !@pg_bin_path
    bin_path = "/Applications/Postgres.app/Contents/Versions/latest/bin"
    @pg_bin_path = bin_path if File.exist?("#{bin_path}/pg_ctl")
  end
  if !@pg_bin_path
    puts "Can not find postgres bin path"
    exit 1
  end
  @pg_bin_path
end

#pg_ctl_pathObject



53
54
55
56
57
58
59
60
# File 'lib/temporary_db.rb', line 53

def pg_ctl_path
  return @pg_ctl_path if @pg_ctl_path

  @pg_ctl_path = `which pg_ctl 2> /dev/null`.strip
  @pg_ctl_path = "#{pg_bin_path}/pg_ctl" if @pg_ctl_path.length == 0

  @pg_ctl_path
end

#pg_portObject



49
50
51
# File 'lib/temporary_db.rb', line 49

def pg_port
  @pg_port ||= find_free_port(11_000..11_900)
end

#port_available?(port) ⇒ Boolean

Returns:

  • (Boolean)


8
9
10
11
12
13
# File 'lib/temporary_db.rb', line 8

def port_available?(port)
  TCPServer.open(port).close
  true
rescue Errno::EADDRINUSE
  false
end

#removeObject



112
113
114
115
# File 'lib/temporary_db.rb', line 112

def remove
  raise "Error: the database must be stopped before it can be removed" if @started
  FileUtils.rm_rf PG_TEMP_PATH
end

#startObject



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/temporary_db.rb', line 62

def start
  FileUtils.rm_rf PG_TEMP_PATH
  `#{initdb_path} -D '#{PG_TEMP_PATH}' --auth-host=trust --locale=en_US.UTF-8 -E UTF8 2> /dev/null`

  FileUtils.mkdir PG_SOCK_PATH
  conf = File.read(PG_CONF)
  File.write(PG_CONF, conf + "\nport = #{pg_port}\nunix_socket_directories = '#{PG_SOCK_PATH}'")

  puts "Starting postgres on port: #{pg_port}"
  ENV["DISCOURSE_PG_PORT"] = pg_port.to_s

  Thread.new { `#{pg_ctl_path} -D '#{PG_TEMP_PATH}' start` }

  puts "Waiting for PG server to start..."
  sleep 0.1 while !`#{pg_ctl_path} -D '#{PG_TEMP_PATH}' status`.include?("server is running")
  @started = true

  `createuser -h localhost -p #{pg_port} -s -D -w discourse 2> /dev/null`
  `createdb -h localhost -p #{pg_port} discourse`

  puts "PG server is ready and DB is loaded"
end

#stopObject



85
86
87
88
# File 'lib/temporary_db.rb', line 85

def stop
  @started = false
  `#{pg_ctl_path} -D '#{PG_TEMP_PATH}' stop`
end

#with_env(&block) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/temporary_db.rb', line 90

def with_env(&block)
  old_host = ENV["PGHOST"]
  old_user = ENV["PGUSER"]
  old_port = ENV["PGPORT"]
  old_dev_db = ENV["DISCOURSE_DEV_DB"]
  old_rails_db = ENV["RAILS_DB"]

  ENV["PGHOST"] = "localhost"
  ENV["PGUSER"] = "discourse"
  ENV["PGPORT"] = pg_port.to_s
  ENV["DISCOURSE_DEV_DB"] = "discourse"
  ENV["RAILS_DB"] = "discourse"

  yield
ensure
  ENV["PGHOST"] = old_host
  ENV["PGUSER"] = old_user
  ENV["PGPORT"] = old_port
  ENV["DISCOURSE_DEV_DB"] = old_dev_db
  ENV["RAILS_DB"] = old_rails_db
end