1

I'm trying to create an rails app to upload file to S3 using carrierwave. I follow the instructions from: https://github.com/carrierwaveuploader/carrierwave#using-amazon-s3. For the local uploading is working fine. But when it comes to S3, it throws this error:

bin/rails:6: warning: already initialized constant APP_PATH
/Users/sancowinx/Code/rails/fileuploadercarrierwave/bin/rails:6: warning: previous definition of APP_PATH was here

after searching from the web I found that there is also rubygem named fog (I was using fog-aws, according to the instructions of the carrierwave with S3 I mention above). Then, I try changing to use rubygem fog instead. Also throws an error. But now it throws exception for undefined method instead:

/Users/sancowinx/Code/rails/fileuploadercarrierwave/config/initializers/carrierwave.rb:2:in `block in <top (required)>': undefined method `fog_provider=' for CarrierWave::Uploader::Base:Class (NoMethodError)

for above exception full log: http://pastebin.com/2AiepK7w

I also found the similar question here. Already follow an instruction but doesn't get me anywhere.

Everything runs on ruby version: 2.2.1, rails version: 4.2.1

Gemfile

source 'https://rubygems.org'

gem 'rails', '4.2.1'
gem 'sqlite3'
gem 'sass-rails', '~> 5.0'
gem 'bootstrap-sass', '~> 3.3.3'
gem 'uglifier', '>= 1.3.0'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'sdoc', '~> 0.4.0', group: :doc

group :development, :test do
  gem 'byebug'
  gem 'web-console', '~> 2.0'
  gem 'spring'
  gem 'better_errors'
  gem 'binding_of_caller'
end

gem 'fog-aws'
gem 'carrierwave', '~> 0.10.0'

Model

class S3Post < ActiveRecord::Base
  mount_uploader :attachment, S3PostUploader
  validates :name, presence: true # validates names
end

Table schema

  create_table "s3_posts", force: :cascade do |t|
    t.string   "name"
    t.string   "attachment"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

Controller

class S3PostsController < ApplicationController
  def index
    @s3posts = S3Post.all
  end

  def new
    @s3post = S3Post.new
  end

  def create
    @s3post = S3Post.new(s3post_params)

    if @s3post.save
      redirect_to s3_posts_path, notice: "The S3Post #{@s3post.name} has been uploaded."
    else
      render 'new'
    end
  end

  def destroy
    @s3post = S3Post.find(params[:id])
    @s3post.destroy

    redirect_to s3_posts_path, notice: "The S3Post #{@s3post.name} has been deleted."
  end

  private
    def s3post_params
      params.require(:s3_post).permit(:name,:attachment)
    end
end

Uploader

# encoding: utf-8

class S3PostUploader < CarrierWave::Uploader::Base

  storage :fog

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  def extension_white_list
    %w(jpg jpeg gif png)
  end

end

config/initializer/carrierwave.rb

CarrierWave.configure do |config|
  config.fog_provider = 'fog-aws'
  config.fog_credentials = {
    :provider               => 'AWS',
    :aws_access_key_id      => ENV['S3_KEY'],
    :aws_secret_access_key  => ENV['S3_SECRET']
  }
  config.fog_directory  = ENV['S3_BUCKET']
end

PS. I store AWS key in my ~/.bash_profile instead of hardcoding.

I've tried uninstall/reinstall fog-aws, carrierwave gem but still cannot make it working. Can anybody help find what I am doing wrong here?

Community
  • 1
  • 1
sancowinx
  • 160
  • 2
  • 12
  • Hartl's Rails tutorial has a section (11.4) on file storage which I found helpful. Just make sure you set up an AWS policy for S3 or you will get 403s. – steve klein Apr 22 '15 at 12:27

1 Answers1

3

The issue is that you're using the currently released version of carrierwave but following the documentation for the master - the two are over a year apart. You can read the README for 0.10.0 on github (https://github.com/carrierwaveuploader/carrierwave/blob/v0.10.0/README.md) or via rubydoc.info. You'll need to either switch to the master version of carrier wave or modify your code to match the older readme.

fog is a gem that attempts to provide a common interface to main cloud providers (AWS, rackspace, google compute etc.), however a consequence of that was that the gem was getting pretty big and that most users would actually only be using a small portion of it. A few months ago the decision was taken to split fog into fog-core, which contains code common to all the providers and then provider specific gems.

fog-aws is the gem that has the AWS specific code (and thus S3). The fog gem still exists, for backwards compatibility but just pulls in all of the extracted gems (it still has some providers in it that have not yet been extracted).

The fog_provider setting in newer version of carrier wave allow you to control whether carrierwave will try and load the legacy fog gem and all of its providers or just a specific one such as fog-aws.

Frederick Cheung
  • 83,189
  • 8
  • 152
  • 174
  • Thanks for pointing out. Didn't notice there was a README page specifically for v0.10.0. Decided to follow the [rubydoc.info](http://www.rubydoc.info/gems/carrierwave#Using_Amazon_S3). I was able to run a rails server now but has to change the rails version to `gem 'rails'` instead of `gem 'rails', '4.2.1'`. Now I got the error `break from proc-closure` instead. But rails server can eventually run now anyway. – sancowinx Apr 23 '15 at 10:36
  • I am not sure but if you're using the documentation for 0.10.0 version, you probably don't wanna put 'gem "fog", "~> 1.3.1' to your Gemfile because this version seems to be very old, so just use 'gem "fog"' – NoDisplayName May 05 '15 at 17:50