Search code examples
ruby-on-railsamazon-s3devisecarrierwavefog

Heroku CarrierWave S3 - can't figure out how to save picture


I need save a picture using "aws.amazon.s3" service. In gem file i have:

gem 'carrierwave'
gem 'rmagick'
gem 'fog'
gem 'sprockets-rails'

I wanna use devise registration controller for adding avatar to my user. I did this:

1)rails g migration add_avatar_to_users avatar:string;
rake db:migrate

2) added this row:

class User < ActiveRecord::Base
  mount_uploader :avatar, AvatarUploader
end

3) create app/uploaders/avatar_uploader

# encoding: utf-8

class AvatarUploader < CarrierWave::Uploader::Base

include CarrierWave::RMagick

# Choose what kind of storage to use for this uploader:
#storage :file
 storage :fog

# 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

# Create different versions of your uploaded files:
 version :thumb do
 process resize_to_fill: [140, 140]
 process convert: 'jpeg'
# process :resize_to_fit => [140, 140]
end
# For images you might use something like this:
 def extension_white_list
   %w(jpg jpeg gif png)
 end
end

4) create app/config/init/carrierwawe.rb

CarrierWave.configure do |config|

config.storage = :fog
config.fog_directory  = "app.#{Rails.env}"  # required,
if Rails.env.production?
  config.fog_credentials = {
    :provider               => 'AWS',                                              # required
    :aws_access_key_id      => ENV["AWS_ACCESS_KEY"],                        # required
    :aws_secret_access_key  => ENV["AWS_SECRET_KEY"],                        # required
    :region                 => 'eu-west-1'
}
config.cache_dir = "#{Rails.root}/tmp/uploads"
config.fog_directory  = ENV["AWS_BUCKET"]                                    # required
config.fog_public     = false


config.fog_attributes = {'Cache-Control'=>'max-age=60'}
config.fog_public     = false               # (optional) public readability,       defaults to true
config.cache_dir = Rails.root.join('tmp','uploads')
config.root = Rails.root.join('tmp')
else
config.fog_credentials = {
    :provider               => 'AWS',
    :aws_access_key_id      => '',
    :aws_secret_access_key  => '',
    :region                 => 'eu-west-1'
}
config.cache_dir = '/home/vagrant/uploads_tmp/tmp/uploads'
config.root = '/home/vagrant/uploads_tmp/tmp'
 end
end

5)My application_controller(added - :username and :avatar, :avatar_cache):

def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password,
                                                         :password_confirmation, :remember_me , :avatar, :avatar_cache ) }
devise_parameter_sanitizer.for(:account_update) {|u| u.permit(:username, :email, :password,
                                                               :password_confirmation, :current_password , :avatar, :avatar_cache ) }
end

6) View: views/devise/registration/new.html.haml

= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name),html: { role: "form" , :multipart => true }) do |f|
      .form-group
    = f.label :avatar do
      = f.file_field :avatar , class: "form-control"
      = f.hidden_field :avatar_cache

7)View: views/devise/registration/edit.html.haml

      .form-group
    - if current_user.avatar.url.present?
      = image_tag(current_user.avatar.url)
      -#= f.label :remove_avatar do
      -#  = f.check_box :remove_avatar
    = f.file_field :avatar,  class: "form-control"
    = f.hidden_field :avatar_cache

8)Routes

devise_for :users
resources  :dashboard
resources  :users
root to: "users#show"

When i go to the http://127.0.0.1:3000/users/sign_in

And fill all fields after this push submit. Console show me that...

enter image description here


Solution

  • I figure out how it should work on Heroky and S3 file: u_proj\config\initializers\carrierwave.rb

    CarrierWave.configure do |config|
    
    if Rails.env.production?
      config.fog_credentials = {
          # Configuration for Amazon S3
          :provider              => 'AWS',
          :aws_access_key_id     => ENV['AWS_ACCESS_KEY'],
          :aws_secret_access_key => ENV['AWS_SECRET_KEY']
      }
      config.fog_directory     =  ENV['S3_BUCKET_NAME']
      config.storage           =  :fog
    else
      config.fog_credentials = {
          :provider               => 'AWS',
          :aws_access_key_id      => '',
          :aws_secret_access_key  => '',
          :region                 => 'eu-west-1'
      }
      config.storage = :file
      config.cache_dir = "#{Rails.root}/public/tmp"
    end
    end
    

    Use this:

    heroku config:set AWS_ACCESS_KEY_ID= add a-key
    heroku config:set AWS_SECRET_ACCESS_KEY= add s-a-key
    heroku config:set S3_BUCKET_NAME= add b-name
    

    then commit and push to heroku that's it