What happened to asset_host in rails 3?
Earlier I can put following code into development.rb and get all assets not present on development:
ActionController::Base.asset_host = proc do |source, request|
unless File.exist?(File.join(RAILS_ROOT, 'public', source.sub(/\?\d+$/, '')))
'http://example.com'
end
end
But in rails 3 there is no such method and google does not help me.
The asset_host config information goes into you environment files, which have changed format slightly:
// environments/production.rb
Infinity::Application.configure do
config.action_controller.asset_host = "http://assets.example.com"
end
I'm not sure this will let you override in the same way as your code, though.
Related
I am using CarrierWave for image uploads on a rails-api application which in turn is consumed by a backbone.js client app. I notice that when there is no default image available it returns /assets/default.png. It in turn has to be http://dev-server:3000/assets/default.png. Here are my configuration settings:
# config/environments/development.rb
CarrierWave.configure do |config|
config.asset_host = "http://dev-server:3000"
end
# Image Uploader
....
def default_url
"/assets/default.png"
end
Where am I going wrong?
I'm using Rails 5 API and Carrierwave too.
A lucky guess got it working for me.
I have a file inside app/uploaders/image_uploader.rb.
The asset_host configuration is set inside this file (at least it works for me):
# encoding: utf-8
class ImageUploader < CarrierWave::Uploader::Base
...
def asset_host
return "http://localhost:3000"
end
end
Hope this works for anyone else in the future having this problem.
[Edit (updated answer)]
Updating my answer to setup asset_host in rails config.
Rails.application.configure do
.
.
config.asset_host = 'http://dev-server:3000'
end
Then you can use asset_url method or image_url method of the helper. Since this is an image, I would recommend placing the image in app/assets/images folder and use image_url.
ActionController::Base.helpers.image_url("default.png")
This will give you the following URL:
http://dev-server:3000/images/default.png
You can try it in the console.
[Old Answer]
Looking at Carrierwave Documentation, it seems like your default_url method should look like this (Carrierwave does not automatically perpend asset_host to the default url):
def default_url
ActionController::Base.helpers.asset_path("default.png")
end
I am assuming that asset_host is setup properly in your Rails configuration. If not, please do so.
I would recommend some of your ideas:
I: Put Host in your environment z.B. development.rb
config.asset_host = 'http://localhost:3000'
II: Create file in config/initializers/carrierwave.rb
# config/initializers/carrierwave.rb
CarrierWave.configure do |config|
config.storage = :file
config.asset_host = ActionController::Base.asset_host
end
III: Edit your uploader to:
def default_url
"#{asset_host}/images/fallback/" + [version_name, "default.png"].compact.join('_')
end
IV: RESTART your server
I solved the problem by looking into the code of carrierwave. This is what I ended up doing:
def default_url
"#{asset_host}#{ActionController::Base.helpers.asset_path("default.png")}"
end
Also make sure that you include the asset_host configuration in your respective environment files.
In my production.rb I set my asset_host to CloudFront like so:
config.action_controller.asset_host = 'http://xxxxxxxx.cloudfront.net'
Now I'm finding that in some circumstances (specifically, outputting JavaScript to be embedded into another site) I need to set the asset_host in the development environment too, the default null won't cut it. Ideally I want to set:
config.action_controller.asset_host = 'http://localhost:3000'
but this port can't be guaranteed, and I'm reluctant to hard-code it. Is there a way to set asset_host to the current domain and port?
Thanks!
You can make use of environment variables or Rails initializer parameters
config.action_controller.asset_host = ENV[ASSET_HOST].empty? ? 'http://' + Rails::Server.new.options[:Host] + ':' + Rails::Server.new.options[:Port] : ENV[ASSET_HOST]
This way if you set the environment variable you use that address otherwise it will use the default.
In Rails 4 we use a dynamic asset_host setting with a proc:
# in /config/environments/development.rb
Rails.application.configure do
config.action_controller.asset_host = Proc.new { |source, request|
# source = "/assets/brands/stockholm_logo_horizontal.png"
# request = A full-fledged ActionDispatch::Request instance
# sometimes request is nil and everything breaks
scheme = request.try(:scheme).presence || "http"
host = request.try(:host).presence || "localhost:3000"
port = request.try(:port).presence || nil
["#{scheme}://#{host}", port].reject(&:blank?).join(":")
}
# more config
end
This code ensures that requests from localhost:3000, localhost:8080, 127.0.0.1:3000, local.dev and any other setup just work.
This value is available during startup and might help:
Rails::Server.new.options[:Port]
Try adding it to the asset_host variable of your development.rb file.
Based on this answer: https://stackoverflow.com/a/13839447/1882605
Try:
class ApplicationController < ActionController::Base
before_filter :find_asset_host
private
def find_asset_host
ActionController::Base.asset_host = Proc.new { |source|
if Rails.env.development?
"http://localhost:3000"
else
{}
end
}
end
I want to have emails I send out with ActionMailer contain images that link back to my app. In my development environment, for example:
<img src="http://myfullappurl.dev/assets/myimage.png">
I have this in my development.rb
config.action_controller.asset_host = 'myfullappurl.dev'
config.action_mailer.asset_host = config.action_controller.asset_host
config.action_mailer.default_url_options = { host: 'myfullappurl.dev', only_path: false }
But I can not get my mail templates to render a full URL in any of these way:
asset_path('myimage.png')
asset_path('myimage.png', only_path: false)
image_url('myimage.png')
A lot of similar questions on this topic are answered by doing something like this:
"#{request.protocol}#{request.host_with_port}#{asset_path('image.png')}"
But because my mails are sent asynchronously with Sidekiq, there is no request object like there would be if they were sent synchronously in a controller.
Is there an obvious thing I am missing, or do I have to fight against Rails to do this? I am using Rails 4, but I am sure that anything that works in 3.1/3.2 should do just fine.
Well this is odd behaviour, but I've resolved this issue. It turns out that unless the action_mailer.asset_host starts with http:// then it will be ignored. There is a Regex in actionpack/lib/action_view/helpers/asset_url_helper.rb that defines a valid ActionMailer URI:
URI_REGEXP = %r{^[-a-z]+://|^(?:cid|data):|^//}
However, if you put a http:// in front of the action_controller.asset_host then you will end up with links to http://http://myfullappurl.dev
So to resolve it I had to add the following to my development.rb
config.action_controller.asset_host = 'myfullappurl.dev'
config.action_mailer.asset_host = 'http://myfullappurl.dev'
Just to be clear, this is Rails 4.0.0beta1 with the emails being sent asynchronously with Sidekiq, I am not sure if this affects Rails 3.
I believe you need to set these in your config
config.action_controller.asset_host = 'http://localhost:3000' #Or your domain
config.action_mailer.asset_host = config.action_controller.asset_host
in your environment file(i.e development.rb) :-
config.action_mailer.asset_host = 'http://localhost:3000' #Or your domain
in your mailer view file:-
<%= image_tag('image_name.jpg') %>
or
<img src="<%= image_url('image.jpg') %>" %>
I'm having this problem with carrierwave+fog+s3 with Amazon cloud front. With the following setup I can upload files to s3 but after uploaded, the S3 Objects URLs I get from my rails app doesn't have the assets_host based URLs i.e I'm expeting the URLs to be looks like this format https://mycloudfrontname.cloudfront.net/uploads/myfile.mp3
But they all appear in this format https://mybucketname.s3.amazonaws.com/uploads/myfile.mp3
What might be wrong here?
CarrierWave.configure do |config|
config.fog_credentials = {
:provider => 'AWS',
:aws_access_key_id => 'XXXX',
:aws_secret_access_key => 'XXXX',
:region => 'us-east-1'
}
config.fog_directory = 'mybucketname'
config.asset_host = 'https://mycloudfrontname.cloudfront.net'
config.fog_public = false
config.fog_attributes = {'Cache-Control' => 'max-age=315576000'}
end
UPDATE:
I found this code bit from Carrierwave's /lib/carrierwave/storage/fog.rb - So if we set the asset_host as on above code snippet this must work right? or is there any other configuration I must do as well?
def public_url
if host = #uploader.asset_host
if host.respond_to? :call
"#{host.call(self)}/#{path}"
else
"#{host}/#{path}"
end
else
# AWS/Google optimized for speed over correctness
case #uploader.fog_credentials[:provider]
when 'AWS'
# if directory is a valid subdomain, use that style for access
if #uploader.fog_directory.to_s =~ /^(?:[a-z]|\d(?!\d{0,2}(?:\d{1,3}){3}$))(?:[a-z0-9\.]|(?![\-])|\-(?![\.])){1,61}[a-z0-9]$/
"https://#{#uploader.fog_directory}.s3.amazonaws.com/#{path}"
else
# directory is not a valid subdomain, so use path style for access
"https://s3.amazonaws.com/#{#uploader.fog_directory}/#{path}"
end
when 'Google'
"https://commondatastorage.googleapis.com/#{#uploader.fog_directory}/#{path}"
else
# avoid a get by just using local reference
directory.files.new(:key => path).public_url
end
end
end
Change config.fog_public to true and add config.asset_host = 'YOUR_CND_ADDRESS'. The asset_host doesn't work when fog_public is false
In your environment file you need to set the asset host. Just add the line below to your config/environments/production.rb file, and you should be okay. Also may want to make sure you're using the latest version of carrierwave and fog gems.
-- config/environments/production.rb
Myapp::Application.configure do
# Use Content Delivery Network for assets
config.action_controller.asset_host = 'https://mycloudfrontname.cloudfront.net'
end
Don't use asset_host. The asset_host setting is for files served by the rails asset helpers. CarrierWave files are handled in a different manner. The config you are looking for is config.fog_host
config.fog_host = 'https://mycloudfrontname.cloudfront.net'
I would like to do something like this
config.default_host = 'www.subdomain.example.com'
in some of my configuration files, so that object_url helpers (ActionView::Helpers::UrlHelper) produce links beginning with http://www.subdomain.example.com
I have tried to search the docs but I did not find anything except ActionMailer docs and http://api.rubyonrails.org/classes/Rails/Configuration.html which is not useful for me, because I do not know in which pat to look. Is there a place which describes the whole structure of Rails::Initializer.config?
asset_host doesn't work for urls
You need to override default_url_options in your ApplicationController (at least in Rails 3)
http://edgeguides.rubyonrails.org/action_controller_overview.html#default-url-options
class ApplicationController < ActionController::Base
def default_url_options
if Rails.env.production?
{:host => "myproduction.com"}
else
{}
end
end
end
Define the default host in your environment config:
# config/environments/staging.rb
MyApp::Application.configure do
# ...
Rails.application.routes.default_url_options[:host] = 'preview.mydomain.com'
# ...
end
Then you can create a URL anywhere in your app:
Rails.application.routes.url_helpers.widgets_url()
Or include the URL helpers in your class:
class MyLib
include Rails.application.routes.url_helpers
def make_a_url
widgets_url
end
end
If you don't define the default host, you will need to pass it as an option:
widgets_url host: (Rails.env.staging? ? 'preview.mydomain.com' : 'www.mydomain.com')
It's also useful to specify things like the protocol:
widgets_url protocol: 'https'
Another way is to set it like this
# config/production.rb
config.action_controller.default_url_options = { host: 'myproduction.com' }
You can easily set :host or/and :only_path parameter for every url_helper.
yours_url(params, :host => "http://example.com", :only_path => Rails.env.test?)
This way you are not setting global default_url_options in your environments, unless you want that.
In Rails 6.1 (at least), application-wide default_url_options can be set as follows:
# config/environments/development.rb
Rails.application.default_url_options = { host: 'localhost', port: 3000 }
Rails.application.configure do
# ...
end
See: https://github.com/rails/rails/issues/29992#issuecomment-761892658
As far as I know, the *_url helpers use the server's configured host name. So for example if my Apache installation is accepting requests for this Rails app at http://www.myapp.com/ then Rails will use that address. That's why the *_url methods in a development environment point to http://localhost:3000 by default.
The asset host suggested in the previous answer will only affect the image_tag, stylesheet_link_tag and javascript_link_tag helpers.
NSD's solution is how I do it, but I had to add a block to make it work with https:
config.action_controller.asset_host = Proc.new { |source, request|
(request ? request.protocol : 'http://') + "www.subdomain.example.com"
}
There's this, but I'm not terribly sure if they're the helpers you're referring to:
ActionController::Base.asset_host = "assets.example.com"
http://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html