Rails + Paperclip + AWS S3 has_attached_file方法:为什么这个String插值不起作用?

时间:2012-07-06 21:41:42

标签: ruby-on-rails amazon-s3 paperclip string-interpolation

这里我有一段代码可以根据我在Ruby中对字符串插值的了解而工作。它在模型类中:“s3_file”

基本上我想要完成的是在将文件保存到AWS S3时,我想将它们保存在运行时使用以下字符串插值创建的文件夹下。我使用Devise和cancan作为授权和身份验证宝石

以下代码有效:

 Paperclip.interpolates :prefix  do |attachment, style|
    "#{Date.today.to_s }/system"
 end

 has_attached_file(  :upload,
                  :path => ":prefix/:basename.:extension",
                  :storage => :s3,
                  :s3_credentials => {:access_key_id => "XXX",
                                      :secret_access_key => "XXX"},
                  :bucket => "XXX"
                )

但是,我正在尝试获取usersemail并将其插入Paperclip块。此代码无法正常工作。此代码的结果不是例外,但@curr_user_email始终为null,因此AWS S3上的文件夹没有名称。但该方法确实创建了一个文件夹。我怎么能纠正这个?

此代码仍然工作

if(@curr_user_signed_in)
  @aPrefix = "#{Date.today.to_s }/#{@curr_user_email}"
else
  @aPrefix = "#{Date.today.to_s }/system"
end

Paperclip.interpolates :prefix  do |attachment, style|
   @aPrefix
end


has_attached_file(  :upload,
                  :path => ":prefix/:basename.:extension",
                  :storage => :s3,
                  :s3_credentials => {:access_key_id => "xxx",
                                      :secret_access_key => "xxx"},
                  :bucket => "xxx"
                )

在我的控制器中,我有一些代码:

  def index
   @s3_files = S3File.all

   @curr_user_signed_in = false
   if(user_signed_in?)
     @curr_user_signed_in = true
     @curr_user_email = current_user.email
   end
   respond_to do |format|
     format.html # index.html.erb
     format.json { render json: @s3_files }
   end
  end

所以真正的问题是这些     @curr_user_signed_in = true     @curr_user_email = current_user.email 正在设置并且不为空,但由于某种原因,它们无法读入回形针块

1 个答案:

答案 0 :(得分:2)

看起来你需要使用回形针插值。真的归功于这个家伙:

https://stackoverflow.com/a/852768/931209

这是我认为可以解决问题的片段。

    # interpolate in paperclip
    Paperclip.interpolates :maybe_user  do |attachment, style|
      @prefix =  "#{Date.today.to_s }/system/"
      if(user_signed_in?)
      {
        @prefix = "#{Date.today.to_s }/#{current_user.id}/"
      }
      @prefix
    end 

...然后

     has_attached_file(:upload,
              :path => ":maybe_user/:basename.:extension",
              :storage => :s3,
              :s3_credentials => {:access_key_id => "XXXXX",
                                  :secret_access_key => "XXX"},
              :bucket => "XXX"
            )

这是回形针网站上的文档:

https://github.com/thoughtbot/paperclip/wiki/interpolations

希望有所帮助!

编辑:如果这给你任何狗屎,只需在字符串中添加.to_s,我认为你应该没事。虽然,我不知道为什么会这样。

更新 - 7月7日 - 内容从

开始

前言:我没有使用过设计。

无法从模型中访问devise中的current_user方法。它仅在控制器中可用。

https://github.com/plataformatec/devise/blob/master/lib/devise/controllers/helpers.rb#L33

您需要将attr_accessor添加到模型(S3File?)给当前用户,然后在模型中引用该实例变量。

控制器:

class S3FileController < ApplicationController

    def create
        s = S3File.new

        if user_signed_in?
            s.current_user = current_user
        else
            s.current_user = nil
        end

        # Alternatively written
        # user_signed_in? ? s.current_user = current_user : s.current_user = nil

        s.upload = params[:file]
        s.save

    end

end

型号:

class S3File < ActiveRecord::Base

    attr_accessor :current_user

    Paperclip.interpolates :maybe_user  do |attachment, style|
      @prefix =  "#{Date.today.to_s }/system/"
      if(@current_user)
      {
        @prefix = "#{Date.today.to_s }/#{current_user.id}/"
      }
      @prefix
    end 

end

我相信这应该有效,因为在保存S3File之前,回形针不处理文件。然后,您可以通过@current_user访问User对象,这样您就可以为插值执行以下操作:

Paperclip.interpolates :prefix  do |attachment, style|
   @pre = "#{Date.today.to_s}/system"
   if(@current_user)
     @pre = "#{Date.today.to_s}/#{@current_user.email}"
    end
    @pre
end

有几点需要注意:

1。)魔术真的来自attr_accessor :current_user,它允许你将current_user对象的值存储到S3File。如果您想存储更多信息,可以根据需要添加任意数量的其他attr_accessors。

2。)并不是说它可能没有用例,但一般来说,你不想从模型中访问控制器可用的方法......这有点打破了MVC的原则,因为身份验证应该在控制器中完成,而不是在模型中完成。我根据自己的经验说这个,很久以前就用authlogic和我的(失败的)结果做了这个。 YMMV,这只是值得深思的。

3。)我很确定你必须在回形针块中进行所有插值。没有太多理由不这样做。

[附录]

4.)控制器中设置的实例变量不可用于模型。它们的范围是它们创建的类...这就是我使用attr_accessor =)的原因

[/附录]

希望这能让你走近一步!祝你好运。