Pergunta

Eu tenho um modelo, digamos Anexos, que usos attachment_fu para aceitar o upload de arquivos do usuário. Eu quero "cópia profunda" (ou em Ruby-ese, clone de profundidade) um anexo, criando assim um novo objeto binário na tabela "db_files".

Descobri que não é bem um problema resolvido ainda. Esta postagem de blog: http://www.williambharding.com/blog / rails / rails-rápido-clonecopy-de-attachment_fu-images /

Mostra um método que supostamente trabalha para armazenamento baseado em sistema de arquivos. Para as lojas à base de db, a "cópia profunda" falha. Um novo "anexo" é criado, mas ele usa o db_file_id pré-existente, realizando assim uma cópia superficial.

db_file_backend.rb de Dentro attachment_fu vejo o método Save:

      # Saves the data to the DbFile model
      def save_to_storage
        if save_attachment?
          (db_file || build_db_file).data = temp_data
          db_file.save!
          self.class.update_all ['db_file_id = ?', self.db_file_id = db_file.id], ['id = ?', id]
        end
        true
      end

Então, eu estou tentando decifrar isso e eu acredito "build_db_file" é algum rubi taquigrafia metaprogramming mágica para DbFile.new embora eu não posso confirmar isso (grepping os shows de origem nenhuma menção a isso, nem posso encontrá-lo no google) .

Eu não tenho certeza do que ele está fazendo, mas minha teoria é que o DB_File está sendo copiado do obj origem como parte da tentativa de "cópia Deep" (no código ligada), portanto, é simplesmente provocando um save em vez de um criar.

A minha teoria inicial era de que o (Anexo) objeto pai seria definida como "novo" em cima de uma tentativa de cópia profunda, assim eu fiz algo como:

 def save_to_storage
    if save_attachment?
      if self.new_record?
        db_file = DbFile.new :data => temp_data
        self.class.update_all ['db_file_id = ?', self.db_file_id = db_file.id], ['id = ?', id]
      end
    end
    true
  end

Isso realmente funciona bem para objetos clonados mas infelizmente todos os testes para envios regulares, não clonados de arquivo falhar. O objeto anexo é criado, mas não dados são gravados DB_File. A teoria é que o objeto pai é salvo pela primeira vez, em seguida, o material DB_File está escrito mais tarde, assim new_record? retorna falso.

Assim, como uma experiência, decidi tentar:

  def save_to_storage
    if save_attachment?
      if self.new_record?
        db_file = DbFile.new :data => temp_data
        self.class.update_all ['db_file_id = ?', self.db_file_id = db_file.id], ['id = ?', id]
      else
        (db_file || build_db_file).data = temp_data
        db_file.save!
        self.class.update_all ['db_file_id = ?', self.db_file_id = db_file.id], ['id = ?', id]
      #end
    end
    true
  end

Isso funciona parcialmente - o DB_File é preenchida mas depois eu recebo um erro no db_file.save! -. Dizer que DB_File é nulo

Então, eu sou uma espécie de frustrado. Eu posso fazer mais alguma tentativa e erro, mas neste momento eu bati minha limitada compreensão de como funciona este plugin. Eu realmente não esperava ou quer gastar tanto tempo com isso, então eu estou relutante em tentar explorar attachment_fu mais longe, mas eu tenho medo que eu vou ter que ir no buraco do coelho para descobrir isso. Todas as ideias ou pensamentos?

Thanks !!

Foi útil?

Solução 2

Ok, então em vez de descobrir como criar um novo DB_File (que é um desperdício no nosso caso particular) destroy_file, eu só remendado-macaco apenas excluir o DB_File se não há mais registros de fixação apontando para ele. Isto pode não ser apropriado se você permitir que alguém "modificar" um DB_File anexo In situ , mas desde que não o fizermos, isso funciona muito bem.

Technoweenie::AttachmentFu::Backends::DbFileBackend.module_eval do
  protected
  def destroy_file
    if db_file && self.class.count( :conditions =>["id <> ? AND db_file_id = ?", self.id, db_file.id] ) == 0
      db_file.destroy 
    end
  end
end

Outras dicas

Esta é apenas uma resposta parcial explicando a chamada build_db_file

Como você suspeita, a chamada build_db_file executa um método gerado através da criação associação belongs_to. A associação é criado aqui:

def self.included(base) #:nodoc:
   Object.const_set(:DbFile, Class.new(ActiveRecord::Base)) unless Object.const_defined?(:DbFile)
   base.belongs_to  :db_file, :class_name => '::DbFile', :foreign_key => 'db_file_id'
end

Assim, a declaração (db_file || build_db_file) leva um objeto DbFile associado existente ou cria um novo se é nulo, e atribui o temp_data à sua data campo binário. O temp_data é, provavelmente, a matriz de bytes com os dados a partir do formulário.

E eu tenho uma pergunta (eu não posso comentar sobre a sua pergunta) - por que não chamar db_file.save! depois de criá-la com

db_file = DbFile.new :data => temp_data

?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top