2013-10-26 28 views
1

我正在創建一個包含文件信息的模型,但是如果存在這樣的文件(通過文件哈希檢查),我應該返回現有的文件模型。但我想知道在控制器中,是否新增或不新。我想我可以返回包含現有模型的模型和布爾變量的數組,但其醜陋的解決方案。Ruby模型查找或創建體系結構

也許我應該將部分文件上傳到另一個模塊或其他東西,但在這個過程中提取的數據幾乎都是模型字段,我不想從該模塊返回它,然後檢查現有文件模型並創建它,如果它是新的。但也許這是正確的方法。

型號:

class SourceFileInfo 
    include Mongoid::Document 
    include Mongoid::Timestamps 

    field :name, type: String 
    field :ext, type: String 
    field :path, type: String 
    field :original_name, type: String 
    field :hash, type: String 

    validates_uniqueness_of :name, :hash 
    validates_presence_of :name, :path 

    belongs_to :user 
    belongs_to :book_info 

    def self.find_or_create_from_params file_params, user 
    # collect file data - name, ext, path 
    require 'securerandom' 
    original_name = file_params.original_filename 

    directory = Rails.root.join("upload") 
    file_id = SecureRandom.hex 
    ext = original_name.split('.').last 

    fb2_file_name = "#{file_id}.#{ext}" 

    file_path = File.join(directory, fb2_file_name) 
    File.open(file_path, "wb") { |f| f.write(file_params.read) } 

    # check file exists in db and return it if it does 
    require 'digest/md5' 
    hash = Digest::MD5.hexdigest(File.read file_path) 
    return SourceFileInfo.where(hash: hash).first if SourceFileInfo.where(hash: hash).exists? 

    # else return new model 
    create(name: file_id, ext: ext, path: file_path, 
      original_name: original_name, user: user) 
    end 
end 

控制器:

def upload_book 
    file_info = SourceFileInfo.find_or_create_from_params(file_params[:file], current_user) 

    BookFileWorker.perform_async file_info.id.to_s 

    render nothing: true 
    end 

預先感謝答案。

回答

1

您不需要覆蓋find_or_create方法,因爲它已經存在並且按照您的要求進行操作。

而是在模型生成哈希你現在的樣子,爲什麼不使用類似的控制器如下:

def upload_book 
    hash = Digest::MD5.hexdigest(File.read(file_path)) 
    file_info = SourceFileInfo.find_or_initialize(hash: hash) 
    if file_info.new_record? 
     ... fill in other info and save record 
    else 
     ... do whatever else 
    end 
end 

那麼你的模型可以通過刪除find_or_create_from_params方法進行清理。

+0

我不一樣,但'new_record?'幫助我。如果它是新的,我會用'new'和'save'替換'create'。謝謝! – zishe

+0

關於你的解決方案 - 我不能得到散列這麼快,首先我應該保存文件,它通過部分傳輸,並且在保存之前我應該​​更改名稱,因爲它可能存在。這樣7行就行了。也許可能是另一種方法,但在這種情況下,它會返回3個變量,涉及創建。但我可以使用散列,只需將它傳遞給'find_or_initialize'方法即可。我會盡力做到這一點,並比較這些解決方案。 – zishe