Class: Shadow

Inherits:
Mongrel::HttpHandler
  • Object
show all
Defined in:
lib/shadow.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config, environment, name, address = '0.0.0.0', port = '2001', sleep = nil) ⇒ Shadow

Returns a new instance of Shadow.



10
11
12
13
14
15
16
# File 'lib/shadow.rb', line 10

def initialize(config, environment, name, address = '0.0.0.0', port = '2001', sleep = nil)
  ActiveRecord::Base.establish_connection(YAML.load_file(config)[environment.to_s])
  ActiveRecord::Base.allow_concurrency = false # AR doesn't release connections fast enough
  @sleep = sleep
  @sync = Sync.new
  @pid = serve(self, name, address, port)
end

Instance Attribute Details

#pidObject (readonly)

Returns the value of attribute pid.



8
9
10
# File 'lib/shadow.rb', line 8

def pid
  @pid
end

Instance Method Details

#find(table, id) ⇒ Object

Finds and returns an ActiveRecord instance (returns a new record if id is nil). Dynamically instantiates an ActiveRecord parent class for each call.



47
48
49
50
# File 'lib/shadow.rb', line 47

def find(table, id)
  klass = Class.new(ActiveRecord::Base) { self.table_name = table }
  id ? klass.find(id) : klass.new
end

#process(request, response) ⇒ Object

Implement the mongrel event handler. Responds to all four HTTP methods.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/shadow.rb', line 19

def process(request, response)
  sleep(rand * @sleep) if @sleep
  table, id = request.params["PATH_INFO"].split("/")

  obj, code = nil, 200
  @sync.synchronize(:EX) do # sad
    begin
      obj = find(table, id)
      case request.params["REQUEST_METHOD"]
        when "PUT", "POST"
          obj.update_attributes(YAML.load(request.body.read))
          obj.save!
        when "DELETE"
          obj.destroy
      end
      obj = obj.attributes
    rescue Object => e
      obj, code = e.to_s, 400
    end
  end
  
  response.start(code) do |head, out|
    head["Content-Type"] = "text/yaml"
    out.write obj.to_yaml
  end
end

#serve(me, name, address, port) ⇒ Object

Configure mongrel and start an instance of ourselves.



53
54
55
56
57
58
59
60
61
62
63
# File 'lib/shadow.rb', line 53

def serve(me, name, address, port)
  fork do
    Mongrel::Configurator.new :host => address, :pid_file => "/tmp/shadow.#{name}.pid" do
      listener :port => port do
        puts "** Serving at #{address}:#{port}/#{name}/ (pid #{Process.pid})"
        uri "/#{name}/", :handler => me
        setup_signals or run and write_pid_file and join
      end
    end
  end
end