carrierwaveuploader / carrierwave-mongoid

Mongoid support for CarrierWave
MIT License
355 stars 165 forks source link

Carrierwave not uploading the file. #154

Open nsantiago2719 opened 8 years ago

nsantiago2719 commented 8 years ago

I have been using carrierwave-mongoid for my projects. But this is the first time that I encounter this problem. I'm trying to upload a Avatar for the user. I have mounted the uploader, configure the options, and followed the steps every time I use carrierwave. But after uploading the avatar field turns out to old every image upload. Here's a code in my controller

def create
  @user = User.new(data)
  if @user.save
    if params[:user][:avatar].present?
      @user.avatar = params[:user][:avatar]
      @user.save
    end
  end
end

I checked the value of params[:user][:avatar] and it returns me the file. But when I checked @user.avatar's value it returns me this path /uploads/user/avatar/56d00fddc001ff0bd5616990/_old_ . Oh and by the way I checked the path but there is nothing.

Divya-Pandit commented 8 years ago

we are facing same issue.Please,let us know if anyone has found solution for this.

streetlogics commented 4 years ago

For any other poor fool who comes across this at a later date, here you are: use .update(avatar: File.open(params[:user][:avatar])) instead! I don't know why, maybe the maintainers can figure it out, but the avatar= method is not behaving the same as the .update method

leoarnold commented 3 years ago

@nsantiago2719 @Divya-Pandit @streetlogics I tried to tackle this issue but was not able to reproduce it. What am I missing? Here is what I tried:

    describe 'Issue 158' do
      let(:model_class) { reset_mongo_class }

      before do
        model_class.create!
      end

      shared_examples 'persist avatar' do
        if Gem::Version.new(Mongoid::VERSION) >= Gem::Version.new(4)
          it 'save', aggregate_failures: true do
            record = model_class.first
            expect(record.image).to be_blank

            record.image = file
            record.save!

            expect(record.image.path).to eq(public_path('uploads/test.jpeg'))
            expect(model_class.first.image.path).to eq(public_path('uploads/test.jpeg'))
          end

          it 'update', aggregate_failures: true do
            record = model_class.first
            expect(record.image).to be_blank

            expect(record.update(image: file)).to be_truthy

            expect(record.image.path).to eq(public_path('uploads/test.jpeg'))
            expect(model_class.first.image.path).to eq(public_path('uploads/test.jpeg'))
          end
        end
      end

      context 'with stub_file' do
        let(:file) { stub_file('test.jpeg') }

        include_examples 'persist avatar'
      end

      context 'with file upload' do
        let(:file) do
          {
            "filename" => "test.jpeg",
            "type" => "image/jpeg",
            "name" => "avatar",
            "tempfile" => stub_tempfile('test.jpeg'),
            "head" => "Content-Disposition: form-data; name=\"avatar\"; filename=\"test.jpeg\"\r\nContent-Type: image/jpeg\r\n"
          }.with_indifferent_access
        end

        include_examples 'persist avatar'
      end
    end
nsantiago2719 commented 3 years ago

@leoarnold , I'm not sure because this was a project of mine 4 years ago and as far as I remember I didn't proceed to use this since I wasn't able to fix that problem in time.

streetlogics commented 3 years ago

@leoarnold

I tried to tackle this issue but was not able to reproduce it. What am I missing? Here is what I tried:

In my code, I was calling account.avatar = File.open("path/to/file"), I would assume that's how stub_file is behaving but not quite sure. One thought may be to try a .reload on the object or re-query for it to ensure it's not just set there manually on the object but didn't actually get updated.

leoarnold commented 3 years ago

@streetlogics The way you describe works. That's what I use day to day with no observable problem (at least in our setup).

Should anyone experience the same issue: Please be specific in what kind of object you are actually assigning.

My hunch is that - in the initial example - params[:user][:avatar] was not a proper file upload, but rather the file in plain text (not binary), i.e. a String and not a File. Or maybe it was a file path on disc or some URI.

streetlogics commented 3 years ago

The way you describe works.

I can assure you it didn't work in my case where I was using File.open, despite your test showing otherwise or what the OP had. Either it's something to do with the way stubfile is working (maybe it's returning an empty file instead of actual contents and that throws it off? ¯_(ツ)/¯ ), or the object needs to actually be reloaded in your test to see whether the value was actually saved correctly despite it appearing to be the case simply because save! didn't throw an error and the values appear to be set correctly on the object (hence the suggestion of trying to reload the instance to see if it was actually persisted).

streetlogics commented 3 years ago

Also - what does your uploader look like?

streetlogics commented 3 years ago

This was what I was using:

class AvatarUploader < CarrierWave::Uploader::Base

  storage :fog

  include CarrierWave::MiniMagick

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  def extension_whitelist
    %w(jpg jpeg png)
  end

  process :resize_to_fill => [300, 300]

end
streetlogics commented 3 years ago

Wondering if maybe it could be something to do with the extra step of uploading to s3 via fog?

leoarnold commented 3 years ago

@streetlogics Our uploader looks quite the same. Also uses S3. Maybe your access to S3 lacks certain permissions, leading to a silent fail. I gave mine full permissions on its S3 bucket.

streetlogics commented 3 years ago

Yah my s3 credentials are setup and working fine. I'm not having the issue anymore as I've implemented my "workaround" using .update instead of avatar = - can't explain why the setter didn't work vs. update, but figured it would help if I posted that and give some guidance on where to look. Take it for what it's worth ¯(ºдಠ)/¯ There's something about your test that's not quite reproducing the issue somehow, but I'm not sure how / what / why. Sorry I don't have more detail to help repro, I know how frustrating these issue can be to try and hunt down. Hopefully if someone else has this issue they have a simpler use case that they can try to post more details on that helps repro.

For reference, here's all the mongo related gems I'm using in case one of them is potentially interacting weirdly:

gem 'mongo', '2.13.0'
gem 'mongoid', github: 'marmont/mongoid', ref: '58d008a06f195c34954275d2c140474336c4a9c5'
gem 'mongoid-slug'
gem 'mongoid_token', github: 'marmont/mongoid_token', ref: 'da951156cf39126dd952bf442ee00fa6037bf18d'
gem "mongo_session_store", '>= 3.2.1'
gem 'mongoid_rails_migrations'
gem 'kaminari-mongoid'
gem 'mongoid-ancestry'
gem 'carrierwave'
gem 'carrierwave-mongoid'
gem 'fog-aws'
streetlogics commented 3 years ago

Here's my config/initializers/carrierwave.rb in case it helps too, maybe it's something with using cache_storage = :file ¯\_(ツ)_/¯ :

CarrierWave.configure do |config|
  endpoint = "https://xyz.cloudfront.net"
  config.fog_credentials = {
    :provider               => 'AWS',
    :aws_access_key_id      => ENV['AWS_ACCESS_KEY_ID'],
    :aws_secret_access_key  => ENV['AWS_SECRET_ACCESS_KEY'],
    :region                 => 'us-east-1',
    :host                   => "s3.amazonaws.com",
    :endpoint               => "https://s3.amazonaws.com"
  }
  config.cache_storage = :file
  config.fog_directory  = ENV['S3_BUCKET_NAME']
  config.asset_host = endpoint
end

module CarrierWave
  module MiniMagick
    def quality(percentage)
      manipulate! do |img|
        img.quality(percentage.to_s)
        img = yield(img) if block_given?
        img
      end
    end
  end
end
leoarnold commented 3 years ago

@streetlogics When you write update(avatar: File.open(params[:user][:avatar])), what is params[:user][:avatar]?

Can you please paste a sample of

puts params[:user][:avatar].inspect