ridley 0.12.0.rc1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -34,7 +34,6 @@ module Ridley
34
34
  autoload :Bootstrapper, 'ridley/bootstrapper'
35
35
  autoload :Client, 'ridley/client'
36
36
  autoload :Connection, 'ridley/connection'
37
- autoload :ChainLink, 'ridley/chain_link'
38
37
  autoload :Chef, 'ridley/chef'
39
38
  autoload :ChefObject, 'ridley/chef_object'
40
39
  autoload :DSL, 'ridley/dsl'
@@ -1,3 +1,5 @@
1
+ require 'shellwords'
2
+
1
3
  module Ridley::Chef
2
4
  class Cookbook
3
5
  # @author Jamie Winsor <reset@riotgames.com>
@@ -125,7 +127,7 @@ module Ridley::Chef
125
127
  end
126
128
 
127
129
  def validate_template(erb_file)
128
- result = quietly { shell_out("erubis -x #{erb_file} | ruby -c") }
130
+ result = quietly { shell_out("erubis -x #{erb_file.shellescape} | ruby -c") }
129
131
  result.error!
130
132
  true
131
133
  rescue Mixlib::ShellOut::ShellCommandFailed
@@ -136,7 +138,7 @@ module Ridley::Chef
136
138
  end
137
139
 
138
140
  def validate_ruby_file(ruby_file)
139
- result = quietly { shell_out("ruby -c #{ruby_file}") }
141
+ result = quietly { shell_out("ruby -c #{ruby_file.shellescape}") }
140
142
  result.error!
141
143
  true
142
144
  rescue Mixlib::ShellOut::ShellCommandFailed
@@ -110,6 +110,15 @@ module Ridley
110
110
  end
111
111
  end
112
112
 
113
+ class HTTPUnknownMethod < HTTPError
114
+ attr_reader :method
115
+
116
+ def initialize(method)
117
+ @method = method
118
+ @message = "unknown http method: #{method}"
119
+ end
120
+ end
121
+
113
122
  class HTTP3XXError < HTTPError; end
114
123
  class HTTP4XXError < HTTPError; end
115
124
  class HTTP5XXError < HTTPError; end
@@ -53,10 +53,10 @@ module Ridley
53
53
  ssh_port, winrm_port = parse_port_options(options)
54
54
  timeout = options[:ssh] && options[:ssh][:timeout]
55
55
 
56
- if connector_port_open?(host, ssh_port, timeout)
57
- host_connector = Ridley::HostConnector::SSH
58
- elsif connector_port_open?(host, winrm_port)
56
+ if connector_port_open?(host, winrm_port)
59
57
  host_connector = Ridley::HostConnector::WinRM
58
+ elsif connector_port_open?(host, ssh_port, timeout)
59
+ host_connector = Ridley::HostConnector::SSH
60
60
  else
61
61
  raise Ridley::Errors::HostConnectionError, "No available connection method available on #{host}."
62
62
  end
@@ -47,10 +47,10 @@ module Ridley
47
47
  end
48
48
 
49
49
  def run(command)
50
+ response = Ridley::HostConnector::Response.new(host)
50
51
  command_uploaders << command_uploader = CommandUploader.new(winrm)
51
52
  command = get_command(command, command_uploader)
52
53
 
53
- response = Ridley::HostConnector::Response.new(host)
54
54
  debug "Running WinRM Command: '#{command}' on: '#{host}' as: '#{user}'"
55
55
 
56
56
  output = winrm.run_cmd(command) do |stdout, stderr|
@@ -25,8 +25,6 @@ module Ridley
25
25
  end
26
26
 
27
27
  include Celluloid
28
- include Chozo::VariaModel
29
- include Comparable
30
28
 
31
29
  # @param [Celluloid::Registry] connection_registry
32
30
  def initialize(connection_registry)
@@ -37,6 +35,7 @@ module Ridley
37
35
  self.class.representation.new(Actor.current, *args)
38
36
  end
39
37
 
38
+ # @return [Ridley::Connection]
40
39
  def connection
41
40
  @connection_registry[:connection_pool]
42
41
  end
@@ -52,12 +51,13 @@ module Ridley
52
51
 
53
52
  # @param [String, #chef_id] object
54
53
  #
55
- # @return [nil, Object]
54
+ # @return [Object, nil]
56
55
  def find(object)
57
56
  chef_id = object.respond_to?(:chef_id) ? object.chef_id : object
58
57
  new(request(:get, "#{self.class.resource_path}/#{chef_id}"))
59
- rescue Errors::HTTPNotFound => ex
60
- nil
58
+ rescue AbortError => ex
59
+ return nil if ex.cause.is_a?(Errors::HTTPNotFound)
60
+ abort(ex.cause)
61
61
  end
62
62
 
63
63
  # @param [#to_hash] object
@@ -68,33 +68,33 @@ module Ridley
68
68
  new_attributes = request(:post, self.class.resource_path, resource.to_json)
69
69
  resource.mass_assign(resource._attributes_.deep_merge(new_attributes))
70
70
  resource
71
- rescue Errors::HTTPConflict => ex
72
- abort(ex)
73
71
  end
74
72
 
75
73
  # @param [String, #chef_id] object
76
74
  #
77
- # @return [Object]
75
+ # @return [Object, nil]
78
76
  def delete(object)
79
77
  chef_id = object.respond_to?(:chef_id) ? object.chef_id : object
80
78
  new(request(:delete, "#{self.class.resource_path}/#{chef_id}"))
79
+ rescue AbortError => ex
80
+ return nil if ex.cause.is_a?(Errors::HTTPNotFound)
81
+ abort(ex.cause)
81
82
  end
82
83
 
83
84
  # @return [Array<Object>]
84
85
  def delete_all
85
- all.collect do |resource|
86
- future(:delete, resource)
87
- end.map(&:value)
86
+ all.collect { |resource| future(:delete, resource) }.map(&:value)
88
87
  end
89
88
 
90
89
  # @param [#to_hash] object
91
90
  #
92
- # @return [Object]
91
+ # @return [Object, nil]
93
92
  def update(object)
94
93
  resource = new(object.to_hash)
95
94
  new(request(:put, "#{self.class.resource_path}/#{resource.chef_id}", resource.to_json))
96
- rescue Errors::HTTPConflict => ex
97
- abort(ex)
95
+ rescue AbortError => ex
96
+ return nil if ex.cause.is_a?(Errors::HTTPConflict)
97
+ abort(ex.cause)
98
98
  end
99
99
 
100
100
  private
@@ -107,10 +107,12 @@ module Ridley
107
107
  # @param [Symbol] method
108
108
  def raw_request(method, *args)
109
109
  unless Connection::METHODS.include?(method)
110
- raise
110
+ raise Errors::HTTPUnknownMethod, "unknown http method: #{method}"
111
111
  end
112
112
 
113
113
  defer { connection.send(method, *args) }
114
+ rescue Errors::HTTPError => ex
115
+ abort(ex)
114
116
  end
115
117
  end
116
118
  end
@@ -49,8 +49,9 @@ module Ridley
49
49
 
50
50
  request(:delete, url)
51
51
  true
52
- rescue Errors::HTTPNotFound
53
- true
52
+ rescue AbortError => ex
53
+ return nil if ex.cause.is_a?(Errors::HTTPNotFound)
54
+ abort(ex.cause)
54
55
  end
55
56
 
56
57
  # Delete all of the versions of a given cookbook on the remote Chef server
@@ -60,9 +61,7 @@ module Ridley
60
61
  #
61
62
  # @option options [Boolean] purge (false)
62
63
  def delete_all(name, options = {})
63
- versions(name).each do |version|
64
- future(:delete, name, version, options)
65
- end.map(&:value)
64
+ versions(name).collect { |version| future(:delete, name, version, options) }.map(&:value)
66
65
  end
67
66
 
68
67
  # Download the entire cookbook
@@ -92,8 +91,9 @@ module Ridley
92
91
  def find(object, version)
93
92
  chef_id = object.respond_to?(:chef_id) ? object.chef_id : object
94
93
  new(request(:get, "#{self.class.resource_path}/#{chef_id}/#{version}"))
95
- rescue Errors::HTTPNotFound
96
- nil
94
+ rescue AbortError => ex
95
+ return nil if ex.cause.is_a?(Errors::HTTPNotFound)
96
+ abort(ex.cause)
97
97
  end
98
98
 
99
99
  # Return the latest version of the given cookbook found on the remote Chef server
@@ -157,8 +157,11 @@ module Ridley
157
157
  url << "?force=true" if options[:force]
158
158
 
159
159
  request(:put, url, cookbook.to_json)
160
- rescue Ridley::Errors::HTTPConflict => ex
161
- abort Ridley::Errors::FrozenCookbook.new(ex)
160
+ rescue AbortError => ex
161
+ if ex.cause.is_a?(Errors::HTTPConflict)
162
+ abort Ridley::Errors::FrozenCookbook.new(ex)
163
+ end
164
+ abort(ex.cause)
162
165
  end
163
166
  alias_method :create, :update
164
167
 
@@ -221,8 +224,11 @@ module Ridley
221
224
  response[name]["versions"].collect do |cb_ver|
222
225
  cb_ver["version"]
223
226
  end
224
- rescue Errors::HTTPNotFound => ex
225
- abort(Errors::ResourceNotFound.new(ex))
227
+ rescue AbortError => ex
228
+ if ex.cause.is_a?(Errors::HTTPNotFound)
229
+ abort Errors::ResourceNotFound.new(ex)
230
+ end
231
+ abort(ex.cause)
226
232
  end
227
233
 
228
234
  private
@@ -16,7 +16,7 @@ module Ridley
16
16
  #
17
17
  # @return [Array<Object>]
18
18
  def all(data_bag)
19
- connection.get("#{DataBagResource.resource_path}/#{data_bag.name}").body.collect do |id, location|
19
+ request(:get, "#{DataBagResource.resource_path}/#{data_bag.name}").collect do |id, location|
20
20
  new(data_bag, id: id)
21
21
  end
22
22
  end
@@ -24,63 +24,61 @@ module Ridley
24
24
  # @param [Ridley::DataBagObject] data_bag
25
25
  # @param [String, #chef_id] object
26
26
  #
27
- # @return [Ridley::DataBagItemObject]
27
+ # @return [Ridley::DataBagItemObject, nil]
28
28
  def find(data_bag, object)
29
29
  chef_id = object.respond_to?(:chef_id) ? object.chef_id : object
30
- new(data_bag).from_hash(connection.get("#{DataBagResource.resource_path}/#{data_bag.name}/#{chef_id}").body)
31
- rescue Errors::HTTPNotFound
32
- nil
30
+ new(data_bag).from_hash(request(:get, "#{DataBagResource.resource_path}/#{data_bag.name}/#{chef_id}"))
31
+ rescue AbortError => ex
32
+ return nil if ex.cause.is_a?(Errors::HTTPNotFound)
33
+ abort(ex.cause)
33
34
  end
34
35
 
35
36
  # @param [Ridley::DataBagObject] data_bag
36
37
  # @param [#to_hash] object
37
38
  #
38
- # @return [Ridley::DataBagItemObject]
39
+ # @return [Ridley::DataBagItemObject, nil]
39
40
  def create(data_bag, object)
40
41
  resource = new(data_bag, object.to_hash)
41
42
  unless resource.valid?
42
43
  abort Errors::InvalidResource.new(resource.errors)
43
44
  end
44
45
 
45
- new_attributes = connection.post("#{DataBagResource.resource_path}/#{data_bag.name}", resource.to_json).body
46
+ new_attributes = request(:post, "#{DataBagResource.resource_path}/#{data_bag.name}", resource.to_json)
46
47
  resource.mass_assign(new_attributes)
47
48
  resource
48
- rescue Errors::HTTPConflict => ex
49
- abort(ex)
50
49
  end
51
50
 
52
51
  # @param [Ridley::DataBagObject] data_bag
53
52
  # @param [String, #chef_id] object
54
53
  #
55
- # @return [Ridley::DataBagItemObject]
54
+ # @return [Ridley::DataBagItemObject, nil]
56
55
  def delete(data_bag, object)
57
56
  chef_id = object.respond_to?(:chef_id) ? object.chef_id : object
58
- new(data_bag).from_hash(connection.delete("#{DataBagResource.resource_path}/#{data_bag.name}/#{chef_id}").body)
57
+ new(data_bag).from_hash(request(:delete, "#{DataBagResource.resource_path}/#{data_bag.name}/#{chef_id}"))
58
+ rescue AbortError => ex
59
+ return nil if ex.cause.is_a?(Errors::HTTPNotFound)
60
+ abort(ex.cause)
59
61
  end
60
62
 
61
63
  # @param [Ridley::DataBagObject] data_bag
62
64
  #
63
65
  # @return [Array<Ridley::DataBagItemObject>]
64
66
  def delete_all(data_bag)
65
- mutex = Mutex.new
66
- deleted = []
67
-
68
- all(data_bag).collect do |resource|
69
- future(:delete, data_bag, resource)
70
- end.map(&:value)
67
+ all(data_bag).collect { |resource| future(:delete, data_bag, resource) }.map(&:value)
71
68
  end
72
69
 
73
70
  # @param [Ridley::DataBagObject] data_bag
74
71
  # @param [#to_hash] object
75
72
  #
76
- # @return [Ridley::DataBagItemObject]
73
+ # @return [Ridley::DataBagItemObject, nil]
77
74
  def update(data_bag, object)
78
75
  resource = new(data_bag, object.to_hash)
79
76
  new(data_bag).from_hash(
80
- connection.put("#{DataBagResource.resource_path}/#{data_bag.name}/#{resource.chef_id}", resource.to_json).body
77
+ request(:put, "#{DataBagResource.resource_path}/#{data_bag.name}/#{resource.chef_id}", resource.to_json)
81
78
  )
82
- rescue Errors::HTTPConflict => ex
83
- abort(ex)
79
+ rescue AbortError => ex
80
+ return nil if ex.cause.is_a?(Errors::HTTPConflict)
81
+ abort(ex.cause)
84
82
  end
85
83
  end
86
84
  end
@@ -24,10 +24,11 @@ module Ridley
24
24
  # @return [nil, Ridley::DataBagResource]
25
25
  def find(object)
26
26
  chef_id = object.respond_to?(:chef_id) ? object.chef_id : object
27
- connection.get("#{self.class.resource_path}/#{chef_id}")
27
+ request(:get, "#{self.class.resource_path}/#{chef_id}")
28
28
  new(name: chef_id)
29
- rescue Errors::HTTPNotFound
30
- nil
29
+ rescue AbortError => ex
30
+ return nil if ex.cause.is_a?(Errors::HTTPNotFound)
31
+ abort(ex.cause)
31
32
  end
32
33
  end
33
34
  end
@@ -19,8 +19,11 @@ module Ridley
19
19
  run_list = Array(run_list).flatten
20
20
  chef_id = environment.respond_to?(:chef_id) ? environment.chef_id : environment
21
21
  request(:post, "#{self.class.resource_path}/#{chef_id}/cookbook_versions", MultiJson.encode(run_list: run_list))
22
- rescue Errors::HTTPNotFound => ex
23
- abort Errors::ResourceNotFound.new(ex)
22
+ rescue AbortError => ex
23
+ if ex.cause.is_a?(Errors::HTTPNotFound)
24
+ abort Errors::ResourceNotFound.new(ex)
25
+ end
26
+ abort(ex.cause)
24
27
  end
25
28
 
26
29
  # Delete all of the environments on the client. The '_default' environment
@@ -29,9 +32,7 @@ module Ridley
29
32
  # @return [Array<Ridley::EnvironmentObject>]
30
33
  def delete_all
31
34
  envs = all.reject { |env| env.name.to_s == '_default' }
32
- envs.collect do |resource|
33
- future(:delete, resource)
34
- end.map(&:value)
35
+ envs.collect { |resource| future(:delete, resource) }.map(&:value)
35
36
  end
36
37
  end
37
38
  end
@@ -34,7 +34,7 @@ module Ridley
34
34
  sumhash = { checksums: Hash.new }.tap do |chks|
35
35
  Array(checksums).each { |chk| chks[:checksums][chk] = nil }
36
36
  end
37
- new(connection.post(self.class.resource_path, MultiJson.encode(sumhash)).body)
37
+ new(request(:post, self.class.resource_path, MultiJson.encode(sumhash)))
38
38
  end
39
39
 
40
40
  # @param [#chef_id] object
@@ -46,13 +46,15 @@ module Ridley
46
46
  # @return [Hash]
47
47
  def commit(object)
48
48
  chef_id = object.respond_to?(:chef_id) ? object.chef_id : object
49
- connection.put("#{self.class.resource_path}/#{chef_id}", MultiJson.encode(is_completed: true)).body
50
- rescue Ridley::Errors::HTTPBadRequest => ex
51
- abort Ridley::Errors::SandboxCommitError.new(ex.message)
52
- rescue Ridley::Errors::HTTPNotFound => ex
53
- abort Ridley::Errors::ResourceNotFound.new(ex.message)
54
- rescue Ridley::Errors::HTTPUnauthorized, Ridley::Errors::HTTPForbidden => ex
55
- abort Ridley::Errors::PermissionDenied.new(ex.message)
49
+ request(:put, "#{self.class.resource_path}/#{chef_id}", MultiJson.encode(is_completed: true))
50
+ rescue AbortError => ex
51
+ case ex.cause
52
+ when Ridley::Errors::HTTPBadRequest; abort Ridley::Errors::SandboxCommitError.new(ex.message)
53
+ when Ridley::Errors::HTTPNotFound; abort Ridley::Errors::ResourceNotFound.new(ex.message)
54
+ when Ridley::Errors::HTTPUnauthorized, Ridley::Errors::HTTPForbidden
55
+ abort Ridley::Errors::PermissionDenied.new(ex.message)
56
+ else; abort(ex.cause)
57
+ end
56
58
  end
57
59
 
58
60
  # Concurrently upload all of the files in the given sandbox
@@ -75,23 +77,23 @@ module Ridley
75
77
  end
76
78
 
77
79
  def update(*args)
78
- raise RuntimeError, "action not supported"
80
+ abort RuntimeError.new("action not supported")
79
81
  end
80
82
 
81
83
  def all(*args)
82
- raise RuntimeError, "action not supported"
84
+ abort RuntimeError.new("action not supported")
83
85
  end
84
86
 
85
87
  def find(*args)
86
- raise RuntimeError, "action not supported"
88
+ abort RuntimeError.new("action not supported")
87
89
  end
88
90
 
89
91
  def delete(*args)
90
- raise RuntimeError, "action not supported"
92
+ abort RuntimeError.new("action not supported")
91
93
  end
92
94
 
93
95
  def delete_all(*args)
94
- raise RuntimeError, "action not supported"
96
+ abort RuntimeError.new("action not supported")
95
97
  end
96
98
 
97
99
  private
@@ -41,7 +41,7 @@ module Ridley
41
41
  #
42
42
  # @return [Array<String, Symbol>]
43
43
  def indexes
44
- connection.get(self.class.resource_path).body.collect { |name, _| name }
44
+ request(:get, self.class.resource_path).collect { |name, _| name }
45
45
  end
46
46
 
47
47
  # Executes the built up query on the search's client
@@ -80,7 +80,7 @@ module Ridley
80
80
  def run(index, query_string, resources_registry, options = {})
81
81
  query_uri = self.class.query_uri(index)
82
82
  query = self.class.build_query(query_string, options)
83
- response = connection.get(query_uri, query).body
83
+ response = request(:get, query_uri, query)
84
84
 
85
85
  case index.to_sym
86
86
  when :node
@@ -1,3 +1,3 @@
1
1
  module Ridley
2
- VERSION = "0.12.0.rc1"
2
+ VERSION = "0.12.0"
3
3
  end
@@ -51,6 +51,57 @@ describe Ridley::HostConnector::WinRM::Worker do
51
51
  end
52
52
  end
53
53
 
54
+ describe "#run" do
55
+ subject(:run) { winrm_worker.run(command) }
56
+ let(:command) { "dir" }
57
+ let(:command_uploader_stub) { double('CommandUploader') }
58
+ let(:stdout) { "stdout" }
59
+ let(:stderr) { nil }
60
+ let(:winrm_stub) { double }
61
+
62
+ before do
63
+ Ridley::HostConnector::WinRM::CommandUploader.stub(:new).and_return(command_uploader_stub)
64
+ winrm_worker.stub(:winrm).and_return(winrm_stub)
65
+ winrm_stub.stub(:run_cmd).and_yield(stdout, stderr).and_return({exitcode: 0})
66
+ end
67
+
68
+ context "when the exit_code is 0" do
69
+ it "returns an :ok with the response" do
70
+ status, response = run
71
+ expect(status).to eq(:ok)
72
+ expect(response.stdout).to eq("stdout")
73
+ end
74
+ end
75
+
76
+ context "when the exit_code is not 0" do
77
+ let(:stderr) { "stderr" }
78
+
79
+ before do
80
+ winrm_stub.stub(:run_cmd).and_yield(stdout, stderr).and_return({exitcode: 1})
81
+ end
82
+
83
+ it "returns an :error with the response" do
84
+ status, response = run
85
+ expect(status).to eq(:error)
86
+ expect(response.stderr).to eq("stderr")
87
+ end
88
+ end
89
+
90
+ context "when an error is raised" do
91
+ let(:stderr) { "error" }
92
+
93
+ before do
94
+ winrm_stub.stub(:run_cmd).and_yield(stdout, stderr).and_raise("error")
95
+ end
96
+
97
+ it "returns an :error with the response" do
98
+ status, response = run
99
+ expect(status).to eq(:error)
100
+ expect(response.stderr).to eq("error")
101
+ end
102
+ end
103
+ end
104
+
54
105
  describe "#chef_client" do
55
106
  subject(:chef_client) { winrm_worker.chef_client }
56
107
 
@@ -96,15 +96,15 @@ describe Ridley::HostConnector do
96
96
 
97
97
  context "when an SSH port is open" do
98
98
  it "returns Ridley::HostConnector::SSH" do
99
- subject.stub(:connector_port_open?).and_return(true)
100
- subject.best_connector_for(host).should eq(Ridley::HostConnector::SSH)
99
+ subject.stub(:connector_port_open?).and_return(false, true)
100
+ expect(subject.best_connector_for(host)).to eq(Ridley::HostConnector::SSH)
101
101
  end
102
102
  end
103
103
 
104
104
  context "when an SSH port isnt open and a WinRM port is open" do
105
105
  it "retrns Ridley::HostConnector::WinRM" do
106
- subject.stub(:connector_port_open?).and_return(false, true)
107
- subject.best_connector_for(host).should eq(Ridley::HostConnector::WinRM)
106
+ subject.stub(:connector_port_open?).and_return(true, false)
107
+ expect(subject.best_connector_for(host)).to eq(Ridley::HostConnector::WinRM)
108
108
  end
109
109
  end
110
110
 
@@ -119,9 +119,9 @@ describe Ridley::HostConnector do
119
119
 
120
120
  context "when a block is provided" do
121
121
  it "yields the best HostConnector to the block" do
122
- subject.stub(:connector_port_open?).and_return(true)
122
+ subject.stub(:connector_port_open?).and_return(false, true)
123
123
  subject.best_connector_for(host) do |yielded|
124
- yielded.should eq(Ridley::HostConnector::SSH)
124
+ expect(yielded).to eq(Ridley::HostConnector::SSH)
125
125
  end
126
126
  end
127
127
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ridley
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0.rc1
5
- prerelease: 7
4
+ version: 0.12.0
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Jamie Winsor
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-09 00:00:00.000000000 Z
12
+ date: 2013-05-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
@@ -306,7 +306,6 @@ files:
306
306
  - lib/ridley/bootstrap_bindings/windows_template_binding.rb
307
307
  - lib/ridley/bootstrapper.rb
308
308
  - lib/ridley/bootstrapper/context.rb
309
- - lib/ridley/chain_link.rb
310
309
  - lib/ridley/chef.rb
311
310
  - lib/ridley/chef/chefignore.rb
312
311
  - lib/ridley/chef/cookbook.rb
@@ -451,9 +450,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
451
450
  required_rubygems_version: !ruby/object:Gem::Requirement
452
451
  none: false
453
452
  requirements:
454
- - - ! '>'
453
+ - - ! '>='
455
454
  - !ruby/object:Gem::Version
456
- version: 1.3.1
455
+ version: '0'
456
+ segments:
457
+ - 0
458
+ hash: 1507028122842257977
457
459
  requirements: []
458
460
  rubyforge_project:
459
461
  rubygems_version: 1.8.23
@@ -1,25 +0,0 @@
1
- module Ridley
2
- # @author Jamie Winsor <reset@riotgames.com>
3
- # @api private
4
- class ChainLink
5
- attr_reader :parent
6
- attr_reader :child
7
-
8
- # @param [Class, Object] parent
9
- # the parent class or object to send to the child
10
- # @param [Class, Object] child
11
- # the child class or instance to delegate functions to
12
- def initialize(parent, child)
13
- @parent = parent
14
- @child = child
15
- end
16
-
17
- def new(*args)
18
- child.send(:new, parent, *args)
19
- end
20
-
21
- def method_missing(fun, *args, &block)
22
- child.send(fun, parent, *args, &block)
23
- end
24
- end
25
- end