8

我正在开发一个使用回形针在 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。

4

3 回答 3

13

经过大量搜索,我在这里找到了答案 - http://tammersaleh.com/posts/managing-heroku-environment-variables-for-local-development

诀窍是完全删除 S3.rb 文件,然后像这样引用模型中的 ENV 变量:

has_attached_file :photo, 
                  #...
                  :storage        => :s3, 
                  :bucket         => ENV['S3_BUCKET'],
                  :s3_credentials => { :access_key_id     => ENV['S3_KEY'], 
                                       :secret_access_key => ENV['S3_SECRET'] }

无论如何,大卫,谢谢你的建议。我不知道您是否想更新 Heroku 文档以说明某些用户必须这样做。不过再次感谢。

于 2010-02-17T03:01:04.477 回答
2

将文件重命名config/initializers/s3.ymlconfig/initializers/s3.rb并尝试一下。

于 2010-02-16T20:16:43.107 回答
1

Here's your problem:

:bucket         => ENV['S3_BUCKET'],

needs to be

:bucket         => <%= ENV['S3_BUCKET'] %>,

i.e. the assignments are not being interpreted.

于 2011-05-03T04:47:21.857 回答