2011-05-12 58 views
8

我正在使用回形針將我的文檔上傳到Amazon S3。當我上傳一個新文檔時,我想自動創建一個帶有我的項目ID的存儲桶。帶動態存儲桶名稱的導軌回形針S3

因此,在我的控制,我有這樣的:

def new 
    @pmdocument = Pmdocument.new 
    @pmdocument.projectmilestone_id=params[:projectmilestone_id] 

其中projectmilestone_id是foreign_key到我的項目(用作我的桶的名字)

我的模式是這樣的:

class Pmdocument < ActiveRecord::Base 
    belongs_to :projectmilestone 
    attr_accessible :id, :name, :description, :projectmilestone_id, :pmdoc, :projectmilestone_attributes 
    attr_protected :pmdoc_content_type, :pmdoc_size 
    accepts_nested_attributes_for :projectmilestone, :allow_destroy => false 
    has_attached_file :pmdoc, 
    :storage => :s3, 
    :bucket => self.projectmilestone_id.to_s, 
    :s3_credentials => File.join(Rails.root, 'config', 's3.yml') 

當網頁加載完畢後,我得到這個錯誤: 未定義的方法`projectmilestone_id」爲#

我檢查了我的控制器,projectmilestone_id字段在那裏正確加載。

我試圖將bucket行更改爲:bucket => self.name,然後錯誤消失。

模型工作正常,因爲projectmilestone_id正確存儲在數據庫中。

我的猜測是它可以鏈接到可訪問的屬性,但它似乎也沒關係。

怎麼了?非常感謝!!!


我真的不明白:

我決定不再(反正壞主意的名稱必須爲所有S3是唯一的)改變我的水桶,但改變我的路徑,而不是。

這是代碼:

:path => proc { |attachment| "#{attachment.istance.projectname}/:attachment/:id/:basename.:extension" }, 

不創建我的項目名稱的第一個文件夾。如果我通過名稱替換項目名稱,或者甚至描述(pmdocuments的另一個字段),它可以工作,但不能用於項目名稱。當然,我檢查了項目名是否正確填充。原因在別處。

任何線索?

回答

10

has_attached_file方法在類的上下文中執行(當文件被加載時),而不是在可以使用屬性和其他實例方法的記錄實例的上下文中執行。 self.name確實有效,但它返回類的名稱("Pmdocument"),而不是記錄的名稱。

但回形針是足以讓你想要的。該documentation on the S3 storage說:

You can define the bucket as a Proc if you want to determine it’s name at runtime. Paperclip will call that Proc with attachment as the only argument.

在你的情況下,它會是這樣的:

has_attached_file :pmdoc, 
    :storage => :s3, 
    :bucket => proc { |attachment| attachment.instance.projectmilestone_id.to_s }, 
    :s3_credentials => File.join(Rails.root, 'config', 's3.yml') 

現在你傳遞一個Prochas_attached_file。塊的內容在您的類加載時不會被評估,但會在需要時再進行評估。回形針然後用attachment作爲參數調用該塊,並使用返回的值作爲存儲桶名稱。

編輯:

不幸的是,該塊當文件被分配運行,而不是在保存記錄。因此,您的所有屬性可能尚未設置(當您確定Pmdocument.new(params[:pmdocument])未確定時,屬性分配的順序)。我想回形針工作的另一種方式,但在此期間,我看到2個選項:

您可以刪除從PARAMS文件中的控制器,並設置當一切準備就緒:

pmdoc = params[:pmdocument].delete(:pmdoc) 
@pmdocument = Pmdocument.new(params[:pmdocument]) 
@pmdocument.pmdoc = pmdoc 

或者,您可以通過before_post_process(請參閱README的「活動」部分)並在after_save callback中運行它來禁用Paperclip後處理。

+0

謝謝你這個非常有幫助的解釋。我是新來的鐵軌和麪向對象編程,我還沒有抓到一切。我做了你上面講的,但顯然,我不能創建一個數字作爲名字的桶。所以我試圖用我的關係來回到項目名稱:proc {| attachment | attachment.instance.projectmilestone.projectcapstone.project.name.to_s}但我有另一個錯誤:「未定義的方法'projectcapstone'爲零:NilClass」。這很奇怪,因爲我的班級沒有經過關係而沒有成功。這次有什麼不對?謝謝!!! – ndemoreau 2011-05-12 21:49:27

+0

當你分配文件時,可能會執行該塊(可能是像'pmdocument.pmdoc = params [...]或'pmdocument.update_attributes(...)'這樣的行)。確保你的對象在賦值之前有一個有效的'projectcapstone'。 – 2011-05-12 22:22:14

+0

事實上,配置選項實際上*可以*給一個帶參數的lambda/proc(附件)保存了我的生活。非常感謝! <3 – dimitarvp 2015-04-12 22:16:34

相關問題