我正在开发一个使用回形针在 Amazon S3 上存储内容的 rails 应用程序。该应用程序托管在 Heroku 上。我正在开发 Ubuntu Karmic。
我将要描述的问题发生在开发(在我的本地主机上)和生产(在 Heroku 上)。
将 S3 凭据传递给回形针的标准方法是将它们放在 config/s3.yml 中,如下所示:
access_key_id: 12345678
secret_access_key: 903490409fdf09fshsfdoif/43432
当我这样做时,一切正常。但这使得与其他人共享我的代码变得困难,因此 Heroku 提出了一种替代方法 - http://docs.heroku.com/config-vars。
他们建议您应该将 S3_KEY 和 S3_SECRET 放入 .bashrc 中,如下所示:
S3_KEY=12345678
export S3_KEY
S3_SECRET=903490409fdf09fshsfdoif/43432
export S3_SECRET
然后他们建议您创建 config/initializers/s3.yml (注意路径略有不同)并将以下内容放入该文件中:
AWS::S3::Base.establish_connection!(
:access_key_id => ENV['S3_KEY'],
:secret_access_key => ENV['S3_SECRET']
)
但是,当我这样做时,回形针会抛出一个摆动器并吐出以下错误消息:
undefined method `stringify_keys' for #<String:0xb6d6c3f4>
/vendor/plugins/paperclip/lib/paperclip/storage.rb:176:in `parse_credentials'
/vendor/plugins/paperclip/lib/paperclip/storage.rb:138:in `extended'
/vendor/plugins/paperclip/lib/paperclip/storage.rb:137:in `instance_eval'
/vendor/plugins/paperclip/lib/paperclip/storage.rb:137:in `extended'
.... other stuff
很明显,这一切都是在 storage.rb 模块中开始的。单步执行堆栈跟踪:
第 176 行的 parse_credentials 方法被标记 - 这是代码中出现的调用:
def parse_credentials creds
creds = find_credentials(creds).stringify_keys
(creds[RAILS_ENV] || creds).symbolize_keys
end
parse_credentials 方法尝试调用另一个方法 find_credentials,我认为这就是问题所在。这是 find_credentials 的代码:
def find_credentials creds
case creds
when File
YAML::load(ERB.new(File.read(creds.path)).result)
when String
YAML::load(ERB.new(File.read(creds)).result)
when Hash
creds
else
raise ArgumentError, "Credentials are not a path, file, or hash."
end
end
我看不到如何使用 find_credentials 方法从我的 .bashrc 文件中读取值。它有两种情况可以从 YAML 中读取,另一种情况是它正在寻找哈希值。
我的模型像这样引用凭据:
has_attached_file :photo,
(some code removed)
:s3_credentials => "#{RAILS_ROOT}/config/initializers/s3.yml",
如果我从模型中删除 :s3_credentials 散列,stringify_keys 错误就会消失,rails 控制台会抛出出现在 find_credentials 方法末尾的错误消息:即“凭据不是路径、文件或散列”。
所以我很难过。我意识到这可能是 Heroku 人员的问题(我实际上将通过电子邮件将此链接发送给他们,希望他们能回答),这也可能是 thinkbot 的问题。
正如我一开始所说,当我采用将密钥和秘密粘贴到 config/s3.yml 的标准方法时,我的应用程序运行良好,但我更喜欢使用 Heroku 建议的方法,因为它让我的事情变得更容易,而且这意味着我可以将我的 repo 存储在我的公共 github 页面上供其他人使用,而无需在 Git 中编写任何客户合并驱动程序以将我的 api 密钥排除在公共域之外。
我尝试将 ENV 变量粘贴到 etc/bash.bashrc 和 ~/.bashrc 中,重新启动后,我仍然遇到同样的问题。问题出现在开发机器和 Heroku 上。我也确保将我的配置变量推送到 Heroku。