Class: SwitchPoint::Proxy

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

Constant Summary collapse

AVAILABLE_MODES =
[:writable, :readonly]
DEFAULT_MODE =
:readonly

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ Proxy

Returns a new instance of Proxy.



8
9
10
11
12
13
14
15
16
# File 'lib/switch_point/proxy.rb', line 8

def initialize(name)
  @initial_name = name
  @current_name = name
  AVAILABLE_MODES.each do |mode|
    model = define_model(name, mode)
    memorize_switch_point(name, mode, model.connection_pool)
  end
  @global_mode = DEFAULT_MODE
end

Instance Attribute Details

#initial_nameObject (readonly)

Returns the value of attribute initial_name.



3
4
5
# File 'lib/switch_point/proxy.rb', line 3

def initial_name
  @initial_name
end

Instance Method Details

#connected?Boolean

Returns:

  • (Boolean)


142
143
144
# File 'lib/switch_point/proxy.rb', line 142

def connected?
  model_for_connection.connected?
end

#connectionObject



138
139
140
# File 'lib/switch_point/proxy.rb', line 138

def connection
  model_for_connection.connection
end

#define_model(name, mode) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/switch_point/proxy.rb', line 18

def define_model(name, mode)
  model_name = SwitchPoint.config.model_name(name, mode)
  if model_name
    model = Class.new(ActiveRecord::Base)
    Proxy.const_set(model_name, model)
    model.establish_connection(SwitchPoint.config.database_name(name, mode))
    model
  elsif mode == :readonly
    # Re-use writable connection
    Proxy.const_get(SwitchPoint.config.model_name(name, :writable))
  else
    Class.new(ActiveRecord::Base)
  end
end

#memorize_switch_point(name, mode, pool) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/switch_point/proxy.rb', line 33

def memorize_switch_point(name, mode, pool)
  switch_point = { name: name, mode: mode }
  if pool.equal?(ActiveRecord::Base.connection_pool)
    if mode != :writable
      raise RuntimeError.new("ActiveRecord::Base's switch_points must be writable, but #{name} is #{mode}")
    end
    switch_points = pool.instance_variable_get(:@switch_points) || []
    switch_points << switch_point
    pool.instance_variable_set(:@switch_points, switch_points)
  elsif pool.instance_variable_defined?(:@switch_point)
    # Only :writable is specified
  else
    pool.instance_variable_set(:@switch_point, switch_point)
  end
end

#modeObject



58
59
60
# File 'lib/switch_point/proxy.rb', line 58

def mode
  thread_local_mode || @global_mode
end

#model_for_connectionObject



123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/switch_point/proxy.rb', line 123

def model_for_connection
  ProxyRepository.checkout(@current_name) # Ensure the target proxy is created
  model_name = SwitchPoint.config.model_name(@current_name, mode)
  if model_name
    Proxy.const_get(model_name)
  elsif mode == :readonly
    # When only writable is specified, re-use writable connection.
    with_writable do
      model_for_connection
    end
  else
    ActiveRecord::Base
  end
end

#readonly!Object



62
63
64
65
66
67
68
# File 'lib/switch_point/proxy.rb', line 62

def readonly!
  if thread_local_mode
    self.thread_local_mode = :readonly
  else
    @global_mode = :readonly
  end
end

#readonly?Boolean

Returns:

  • (Boolean)


70
71
72
# File 'lib/switch_point/proxy.rb', line 70

def readonly?
  mode == :readonly
end

#reset_name!Object



119
120
121
# File 'lib/switch_point/proxy.rb', line 119

def reset_name!
  @current_name = @initial_name
end

#switch_name(new_name, &block) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/switch_point/proxy.rb', line 105

def switch_name(new_name, &block)
  if block
    begin
      old_name = @current_name
      @current_name = new_name
      block.call
    ensure
      @current_name = old_name
    end
  else
    @current_name = new_name
  end
end

#thread_local_modeObject



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

def thread_local_mode
  Thread.current[:"switch_point_#{@current_name}_mode"]
end

#with_connection(new_mode, &block) ⇒ Object



94
95
96
97
98
99
100
101
102
103
# File 'lib/switch_point/proxy.rb', line 94

def with_connection(new_mode, &block)
  unless AVAILABLE_MODES.include?(new_mode)
    raise ArgumentError.new("Unknown mode: #{new_mode}")
  end
  saved_mode = self.thread_local_mode
  self.thread_local_mode = new_mode
  block.call
ensure
  self.thread_local_mode = saved_mode
end

#with_readonly(&block) ⇒ Object



86
87
88
# File 'lib/switch_point/proxy.rb', line 86

def with_readonly(&block)
  with_connection(:readonly, &block)
end

#with_writable(&block) ⇒ Object



90
91
92
# File 'lib/switch_point/proxy.rb', line 90

def with_writable(&block)
  with_connection(:writable, &block)
end

#writable!Object



74
75
76
77
78
79
80
# File 'lib/switch_point/proxy.rb', line 74

def writable!
  if thread_local_mode
    self.thread_local_mode = :writable
  else
    @global_mode = :writable
  end
end

#writable?Boolean

Returns:

  • (Boolean)


82
83
84
# File 'lib/switch_point/proxy.rb', line 82

def writable?
  mode == :writable
end