Carrierwave JSON response contains relative url but I want absolute url - ruby-on-rails

Carrierwave is returning a JSON response like this:
"url": "/mys3bucket/uploads/entrees/photo/32/4c312e9aed37a59319096a03_1.jpg",
I need the absolute url. Images are hosted on Amazon S3. How can I get the absolute url?
My temporary hack is to add following to Carrierwave initializer:
config.asset_host = "s3.#{ENV.fetch('AWS_REGION')}.amazonaws.com/mybucket"

CarrierWave uses the combination of the filename and the settings
specified in your uploader class to generate the proper URL. This
allows you to easily swap out the storage backend without making any
changes to your core application.
That said, you cannot store the full URL. You can set CarrierWave's asset_host config setting that is based on envrionment.
What storage are you using on Production? Here is my configuration and It works very well. Hope it helps.
CarrierWave.configure do |config|
config.root = Rails.root
if Rails.env.production?
config.storage = :fog
config.fog_credentials = {
provider: "AWS",
aws_access_key_id: ENV["AWS_ACCESS_KEY_ID"],
aws_secret_access_key: ENV["AWS_SECRET_ACCESS_KEY"],
region: ENV["S3_RESION"]
}
config.fog_directory = ENV["S3_BUCKET_NAME"]
# config.asset_host = ENV["S3_ASSET_HOST"]
else
config.storage = :file
# config.asset_host = ActionController::Base.asset_host
end
end

Related

Can carrierwave direct upload to local storage?

Sometimes I am away from internet and still need to work on upload pages. Carrierwave Direct seems to force storage :fog; with no way of overriding in dev.
Is it possible to tell Carrierwave Direct to use local storage (:file) and simply fallback to Carrierwave's development config settings?
Setting storage :file in carrierwave initializer under development config settings doesnt work...carrierwave_direct errors with "is not a recognized provider" from "<%= direct_upload_form_for #uploader do |f| %>".
I have attempted to work around carrierwave direct, but between forcing :fog, expecting a redirect url and expecting the direct_upload_form_for form method...carrierwave_direct is pretty much in charge.
Using storage :file in development would be a welcome feature for the carrierwave_direct gem. Does anyone know how to cleanly do this?
I think it can be done as follows:
CarrierWave.configure do |config|
if Rails.env.development? || Rails.env.test?
config.storage = :file
config.asset_host = ENV["dev_url"]
else
config.fog_provider = 'fog/aws' # required
config.fog_credentials = {
provider: 'AWS', # required
aws_access_key_id: ENV["aws_id"], # required
aws_secret_access_key: ENV["aws_key"], # required
region: ENV["aws_zone"] # optional, defaults to 'us-east-1'
}
config.fog_directory = ENV["aws_bucket"] # required
config.max_file_size = 600.megabytes # defaults to 5.megabytes
config.use_action_status = true
config.fog_public = false # optional, defaults to true
config.fog_attributes = { cache_control: "public, max-age=#{365.day.to_i}" } # optional, defaults to {}
end
end
And in your Uploader add in:
class SomeUploader < CarrierWave::Uploader::Base
if Rails.env.development? || Rails.env.test?
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
end

Carrierwave + Rails + Cloudfront images returning 500, rails assets is serving

I have this configuration so far....
CarrierWave.configure do |config|
config.fog_provider = 'fog/aws'
config.fog_credentials = {
provider: 'AWS', # required
aws_access_key_id: Rails.application.secrets.s3_key, # required
aws_secret_access_key: Rails.application.secrets.s3_secret, # required
region: Rails.application.secrets.s3_region, # optional, defaults to 'us-east-1'
}
# For testing, upload files to local `tmp` folder.
if Rails.env.test? || Rails.env.cucumber? #|| Rails.env.development?
config.storage = :file
config.enable_processing = false
config.root = "#{Rails.root}/tmp"
else
config.storage = :fog
end
config.asset_host = 'http://mycdn.mydomain.com'
config.fog_directory = Rails.application.secrets.s3_bucket
config.fog_public = true
end
http://mycdn.mydomain.com/production/uploads/1/31/dc5d27e2-bd9d-4ba5-8db2-bcbefa52be78.png
# 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
"#{Rails.env}/uploads/#{model.user_id}/#{model.id}"
end
My Rails assets in /assets is working... It's the bucket/directory where Carrierwave is uploading my images that is returning a 500 Error.
Ex: http://mycdn.mydomain.com/production/uploads/3/33/74b1602e-1b9c-4ffd-a53b-bba2323bdb3f.png 500 (Internal Server Error)
Does anyone know what I am missing in my Cloudfront or S3 configuration? Could this be a bucket policy issue? or something else?
Thanks in advance

CarrierWave With Cloudfront Generating wrong URL

Hello I am using Cloudfront with CarrierWave and S3. For some reason in my app I am getting very strange URLs for my cloudfront path when using image_tag and I don't know where I am going wrong. Here is my carrierwave config file
CarrierWave.configure do |config|
config.fog_provider = 'fog/aws' # required
config.fog_credentials = {
provider: 'AWS', # required
aws_access_key_id: 'accesskey', # required
aws_secret_access_key: 'secretaccess key', # required
region: 'us-east-1', # optional, defaults to 'us-east-1'
}
config.fog_directory = 'bwautosales' # required
# config.asset_host = 'randomletters.cloudfront.net'
config.asset_host = 'randomletters.cloudfront.net'
config.fog_public = true
config.fog_attributes = { 'Cache-Control' => "max-age=#{365.day.to_i}" } # optional, defaults to {}
end
and my production.rb file I have
config.action_controller.asset_host = 'randomletters.cloudfront.net'
but in my view when I do something like
<%= link_to image_tag(car.images[0], class: "img-responsive right-block", id: index), car %>
I get this -
src = https://randomletters.cloudfront.net/images/randomletters.cloudfront.net/uploads/car/images/28/car.png"
I'm sure this is an easy fix but don't know where I'm going wrong. Any help would be appreciated!
Image Uploader `
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :fog
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def extension_whitelist
%w(jpg jpeg gif png)
end
end
`
In your Carrierwave initializer change the line,
config.asset_host = 'randomletters.cloudfront.net' to config.asset_host = 'http://randomletters.cloudfront.net' to get the required cloudfront URL you needed.
You can also remove the line, config.action_controller.asset_host = 'randomletters.cloudfront.net' from Production.rb as the carrierwave itself fetches from the cloud-front url.
CarrierWave.configure do |config|
config.fog_provider = 'fog/aws'
config.fog_credentials = {
--------------
--------------
}
config.fog_directory = 'bwautosales'
config.asset_host = 'http://randomletters.cloudfront.net' # please check the change in this line.
config.fog_public = true
config.fog_attributes = { 'Cache-Control' => "max-age=#{365.day.to_i}" } # optional, defaults to {}
end
Just for the sake of adding credibility to Sravan's answer, I had the same problem and when I followed his instructions it started working properly. If you leave out the http:// from
config.asset_host = <>
It gets confused and tries to use a different path with your site's domain name. I had the same issue, but adding http:// to the beginning of the url fixed it.

Carrierwave fog local storage full attachment path

I am building a rails app with carrierwave and fog for attachment storage. In my test environment, I am using fog local storage.
I am looking for a way to get the full attachment path with this configuration.
CarrierWave.configure do |config|
config.fog_credentials = {
provider: 'Local',
local_root: '/Users/me/fog',
endpoint: '/Users/me/fog',
}
config.fog_directory = 'test.myapp.com
config.fog_public = false
config.fog_attributes = { 'Cache-Control' => 'max-age=315576000' }
end
When I use any other storage options (like AWS S3), I can get the full url to an attachment just by doing my_object.my_attachment_url or my_object.my_attachment.path.
However, when using Local storage, I only get a relative path to my configuration options like my_object/my_attachment/1/test.jpg.
Is there any way through carrierwave or fog to get the full path to this local file?
For my example, the output I am looking for would be: /Users/me/fog/test.myapp.com/my_object/my_attachment/1/test.jpg
For me, the answer was modifying to carrierwave uploader class.
I had
def store_dir
"#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
which worked fine for AWS S3 as all the S3 specific info was inserted before this string. However, to get this to work with fog Local as well, I added:
if Rails.env.test?
def base_path
"#{File.expand_path(CONFIG.fog_local_root)}/#{CONFIG.fog_directory}/"
end
else
def base_path
''
end
end

Configure Environment to Use Different Storage Paths on Amazon S3 with Carrierwave

I would like to have distinct folders in my S3 bucket to keep the production database clear from the development environment.
I am not sure how to do this, here is the skeleton I've come up with in the carrierwave initializer:
if Rails.env.test? or Rails.env.development?
CarrierWave.configure do |config|
//configure dev storage path
end
end
if Rails.production?
CarrierWave.configure do |config|
//configure prod storage path
end
end
Two options:
Option1: You don't care about organizing the files by model ID
In your carrierwave.rb initializer:
Rails.env.production? ? (primary_folder = "production") : (primary_folder = "test")
CarrierWave.configure do |config|
# stores in either "production/..." or "test/..." folders
config.store_dir = "#{primary_folder}/uploads/images"
end
Option 2: You DO care about organizing the files by model ID (i.e. user ID)
In your uploader file (i.e. image_uploader.rb within the uploaders directory):
class ImageUploader < CarrierWave::Uploader::Base
...
# Override the directory where uploaded files will be stored.
def store_dir
Rails.env.production? ? (primary_folder = "production") : (primary_folder = "test")
# stores in either "production/..." or "test/..." folders
"#{primary_folder}/uploads/images/#{model.id}"
end
...
end
Consider the following initializer:
#config/initializers/carrierwave.rb
CarrierWave.configure do |config|
config.enable_processing = true
# For testing, upload files to local `tmp` folder.
if Rails.env.test?
config.storage = :file
config.root = "#{Rails.root}/tmp/"
elsif Rails.env.development?
config.storage = :file
config.root = "#{Rails.root}/public/"
else #staging, production
config.fog_credentials = {
:provider => 'AWS',
:aws_access_key_id => ENV['S3_KEY'],
:aws_secret_access_key => ENV['S3_SECRET']
}
config.cache_dir = "#{Rails.root}/tmp/uploads" # To let CarrierWave work on heroku
config.fog_directory = ENV['S3_BUCKET']
config.fog_public = false
config.storage = :fog
end
end
In development, the uploads are sent to the local public directory.
In test mode, to the Rails tmp directory.
And finally, in "else" environment (which is usually a production or staging environment) we direct the files to S3 using Environmental Variables to determine which bucket and AWS credentials to use.
Use different Amazon s3 buckets for your different environments. In your various environment .rb files, set the environment specific asset_host. Then you can avoid detecting the Rails environment in your uploader.
For example, in production.rb:
config.action_controller.asset_host = "production_bucket_name.s3.amazonaws.com"
The asset_host in development.rb becomes:
config.action_controller.asset_host = "development_bucket_name.s3.amazonaws.com"
etc.
(Also consider using a CDN instead of hosting directly from S3).
Then your uploader becomes:
class ImageUploader < CarrierWave::Uploader::Base
...
# Override the directory where uploaded files will be stored.
def store_dir
"uploads/images/#{model.id}"
end
...
end
This is a better technique from the standpoint of replicating production in your various other environments.

Resources