Question

Not sure how to post this question, so I'l just throw it out here:

I'm using Carrierwave on a polymorphic attachment model:

class Attachment < ActiveRecord::Base
  mount_uploader :file, AttachmentUploader, :mount_on => :file_name

  belongs_to :attachable, :polymorphic => true

  before_save :update_file_attributes

  validates :file, file_size: { maximum: 15.megabytes.to_i }

  private

    def update_file_attributes
      if file.present? && file_name_changed?
        self.digest = Digest::MD5.new.file(file.file.path).hexdigest
      end
    end
end

One of the models having attachments is Ticket:

class Ticket < ActiveRecord::Base

  has_many :attachments, :as => :attachable, dependent: :destroy

  accepts_nested_attributes_for :attachments,
    allow_destroy: true,
    reject_if: proc { |attrs|
      attrs['file'].blank?
    }

  belongs_to :project
  belongs_to :owner, class_name: 'User', foreign_key: :owner_id

end

My uploader creates 2 versions: (based on code found in the Carrierwave wiki)

class AttachmentUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  storage :file

  def store_dir
    "uploads/projects/#{model.attachable.project.to_param}/attachments/#{model.id}/#{model.digest}/"
  end

  version :large do
    process resize_to_fit: [700, 700]
    def full_filename (for_file = model.file.file)
      "large.#{model.file.file.extension}"
    end
  end

  version :thumbnail, from_version: :large do
    process resize_to_fill: [250, 250]
    def full_filename (for_file = model.file.file.extension)
      "thumbnail.#{model.file.file.extension}"
    end
  end
end

And this all works like a charm when uploading, but when destroying it raises:

SystemStackError (stack level too deep):
  actionpack (4.0.4) lib/action_dispatch/middleware/reloader.rb:70

At first I thought it had something to do with accepts_nested_attributes_for, but running Attachment.first.destroy! resulted in the same.

So my question, how should one debug this, as a SystemStackError doesn't show a trace?

Was it helpful?

Solution

It turns out that the Carrierwave wiki can be misleading.

I assumed that model.file.file.extension could be used in full_filename as well. Turns out it can't: model.file.file uses the full_filename to fetch the filename. So this was creating a infinite loop and thus a SystemStackError.

The solution I went for was a simple File.extname:

class AttachmentUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  storage :file

  def store_dir
    "uploads/projects/#{model.attachable.project.to_param}/attachments/#{model.id}/#{model.digest}/"
  end

  version :large do
    process resize_to_fit: [700, 700]
    def full_filename (for_file = model.file.file)
      "large#{File.extname(for_file)}"
    end
  end

  version :thumbnail, from_version: :large do
    process resize_to_fill: [250, 250]
    def full_filename (for_file = model.file.file.extension)
      "thumbnail#{File.extname(for_file)}"
    end
  end
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top