القضبان، Attachment_fu - نسخة عميقة من مرفقات تخزين قاعدة البيانات

StackOverflow https://stackoverflow.com/questions/2205110

سؤال

لدي نموذج، دعنا نقول المرفقات، والتي تستخدم الملحق_FU لقبول تحميل الملفات من المستخدم. أريد أن "نسخة عميقة" (أو في Ruby-ese، استنساخ عميق) مرفق، وبالتالي إنشاء كائن ثنائي جديد تماما في جدول "DB_Files".

لقد وجدت أنها ليست مشكلة حل تماما حتى الآن. نشر بلوق هذا:http://www.williambharding.com/blog/Rails/Rails-faster-clonecopy-of-Actachment_fu-Images/

يظهر الطريقة التي يزعم أنها تعمل في التخزين المستندة إلى نظام الملفات. بالنسبة للمخازن المستندة إلى DB، فشل "النسخة العميقة". يتم إنشاء "مرفق" جديد ولكنه يستخدم DB_File_ID الموجود مسبقا، وبالتالي أداء نسخة ضحلة.

داخل Attachment_fu's db_file_backend.rb أرى طريقة حفظ:

      # 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

لذلك، أحاول فك هذا وأعتقد أن "build_db_file" هو بعض الاختصار السحرية ل Ruby Metaprogramming ل DBFILE.NEW على الرغم من أنني لا أستطيع تأكيد هذا (GREPPING المصدر لا يذكر ذلك، ولا يمكنني العثور عليه على Google).

لست متأكدا تماما ما يفعله، لكن نظريتي هي أن DB_File يتم نسخها من المصدر OBJ كجزء من محاولة "النسخة العميقة" (في التعليمات البرمجية المرتبطة)، وبالتالي تشغيل ببساطة عن حفظ بدلا من يزيد.

كانت نظريتي الأولية هي أن كائن الوالدين (المرفق) سيتم تعيين "جديد" عند محاولة نسخ عميقة، وبالتالي فعلت شيئا مثل:

 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

يعمل هذا في الواقع بشكل جيد للأشياء المستنسخة ولكن لسوء الحظ فشلت جميع الاختبارات لعملية تحميل الملفات العادية غير المستنسخة. يتم إنشاء كائن المرفق ولكن لا تتم كتابة بيانات إلى DB_File. النظرية هي أن الكائن الأصل يتم حفظه أولا، ثم يتم كتابة الأشياء DB_File لاحقا، وبالتالي new_record؟ إرجاع خطأ.

لذلك، كتجربة قررت تجربة:

  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

يعمل ذلك جزئيا - يتم ملء DB_File ولكن بعد ذلك أحصل على خطأ في DB_File.Save! - قائلا أن db_file لا شيء.

لذلك، أنا نوع من المتعلمين. يمكنني أن أفعل بعض التجربة والخطأ الأخرى ولكن في هذه المرحلة، فقد أصبت بفهمي المحدود لكيفية أن يعمل هذا البرنامج المساعد. لم أكن أتوقع أو أرغب في قضاء هذا الوقت الكثير من الوقت لذلك أنا متردد في محاولة واستكشاف التعلق_FU أبعد من ذلك، لكنني أخشى أن أذهب إلى أسفل ثقب الأرنب لمعرفة ذلك. أي أفكار أو أفكار؟

شكرا!!

هل كانت مفيدة؟

المحلول 2

حسنا، لذا بدلا من معرفة كيفية إنشاء DB_File جديد (وهو مهدر في حالتنا الخاصة)، أنا فقط Monkey-bratched DIMED_FILE لحذف DB_File فقط إذا لم يكن هناك المزيد من سجلات المرفقات التي تشير إليها. قد لا يكون هذا مناسبا إذا سمحت لشخص ما "بتعديل" مرفق DB_File فى الموقع ولكن لأننا لا نفعل ذلك، وهذا يعمل بشكل رائع.

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

نصائح أخرى

هذا مجرد استجابة جزئية تشرح build_db_file يتصل

كما اشتبهت، build_db_file تنفذ المكالمة طريقة ولدت من خلال خلق belongs_to منظمة. وبعد يتم إنشاء الجمعية هنا:

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

لذلك (db_file || build_db_file) بيان يأخذ حالية مرتبطة DbFile كائن، أو إنشاء واحدة جديدة إذا كان الأمر لا يحتوي على NIL، ويعين temp_data على حقلها الثنائي data. وبعد ال temp_data ربما صفيف البايت مع البيانات من النموذج.

ولدي سؤال واحد (لا أستطيع التعليق على سؤالك) - لماذا لا تتصل db_file.save! بعد خلقها مع

db_file = DbFile.new :data => temp_data

?

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top