コメントより追記
2015/9月現在、aws-sdk (2.1.23)が本文書の問題に対応しているそうです。
capistrano3のスクリプト中でaws-sdk v2を使うと以下のようなエラーが起きてハマったのでメモしておきます。
Aws::Resources::Errors::DefinitionError: unable to define method Aws::EC2::DhcpOptions#delete, method already exists
発生状況
Capfileの末尾にrequire "aws-sdk"を書いて、deploy.rb内でAws::EC2::Resource.newしたら発生。
原因
どうもaws-sdk-resources-2.0.28/lib/aws-sdk-resources/operation_methods.rb:72でdefine_methodしている箇所との食い合わせが悪い様子。deleteメソッドを定義しようとしたらすでに定義されててダメーという感じ。
68 def safe_define_method(method_name, &block)
69 if instance_methods.include?(method_name.to_sym)
70 msg = "unable to define method #{name}##{method_name}, "
71 msg << "method already exists"
72 raise Errors::DefinitionError, msg
73 else
74 define_method(method_name, &block)
75 end
76 end
ancestorsを見てみると、capistrano/setup
とか capistrano/deploy
をrequireした時点で余計なクラスが挟まっている。このせいで、未定義のはずのメソッドが参照できてしまい、エラーになっている模様。
# 正常に動くケースのancestors
[Aws::EC2::DhcpOptions, Aws::Resources::Resource, Object, JSON::Ext::Generator::GeneratorMethods::Object, Kernel, BasicObject]
# エラーになるケースのancestors
[Aws::EC2::DhcpOptions, Aws::Resources::Resource, Object, JSON::Ext::Generator::GeneratorMethods::Object, Capistrano::DSL, Capistrano::DSL::Stages, Capistrano::DSL::Paths, Capistrano::DSL::Env, Capistrano::TaskEnhancements, Kernel, BasicObject]
対策
capistrano/*
をrequireする前にsafe_define_methodを通してしまえ!という乱暴な方法しか思いつかなかった。とりあえず期待通り動いた感じがするけど、良い対応の仕方ではない・・・。より良いアイデアあれば教えていただけると幸いです。
# aws-sdkを先にrequireしてsafe_define_methodを通してしまうおまじない
require 'aws-sdk'
Aws::EC2::Resource
# Load DSL and set up stages
require 'capistrano/setup'
# Include default deployment tasks
require 'capistrano/deploy'
...
...