Paperclip S3使用存储在模型中的S3凭证上传

时间:2013-10-04 20:40:16

标签: ruby-on-rails amazon-web-services amazon-s3 paperclip

我有一个Site模型,允许通过Paperclip将background_image上传到S3。奇怪的是,每个站点在其模型中都有自己的S3凭证存储。我的问题是,在通过Paperclip上传时如何引用网站自己的属性?

class Site < ActiveRecord::Base
  attr_accessible :background_image, 
                  :s3_access_key_id,
                  :s3_secret_access_key,
                  :s3_username

  has_attached_file :background_image,
                    storage: :s3,
                    s3_credentials: {
                      access_key_id: @s3_access_key_id.to_s,
                      secret_access_key: @s3_secret_access_key.to_s
                    },
                    bucket: "my-app",
                    s3_permissions: "public-read",
                    path: "/home/#{@s3_username}/background_images/:id/:filename"
end

不幸的是,通过此设置,我得到了The AWS Access Key Id you provided does not exist in our records。我假设它只是获取空白值,因为当我对数据库中的值进行硬编码时它可以正常工作。

1 个答案:

答案 0 :(得分:1)

这里的问题是has_attached_fileSite 在首次读取site.rb时被调用,而不是在网站实例上。幸运的是,paperclip支持在几个地方进行动态配置,您可以在运行时检索Site 实例。试试这个:

has_attached_file :background_image,
  s3_credentials: lambda { |attachment| attachment.instance.s3_keys },
  path: lambda { |attachment| "/home/#{attachment.instance.s3_username}/background_images/:id/filename" }


def s3_keys
  {
    access_key_id: self.s3_access_key_id.to_s,
    secret_access_key: self.s3_secret_access_key.to_s
  }
end

将在运行时评估这些lambda,并将Paperclip::Attachment对象作为参数传入。您可以使用Site检索Paperclip::Attachment#instance实例。那么你可以调用实例上的方法来获取它的特定键。

您还可以使用更具体/更高级的技巧将s3_username放入路径中。你可以教回形针更多的路径名插值。就像你可以在config/initializers/paperclip.rb添加一个文件:

Paperclip.interpolates :s3_username do |attachment, style|
  attachment.instance.s3_username
end

然后您的Site模型看起来像

has_attached_file :background_image,
  s3_credentials: lambda { |attachment| attachment.instance.s3_keys },
  path: "/home/:s3_username/background_images/:id/:filename"


def s3_keys
  {
    access_key_id: self.s3_access_key_id.to_s,
    secret_access_key: self.s3_secret_access_key.to_s
  }
end