Since I am currently using nginx to serve public/uploads only in subdomain assets, and also I am using the client side template(eco) to render the image (so I cannot use image_tag or image_url helper method provided by rails), I need to set the model.image_url (which provided by carrierwave) to return url with same domain.
Here is what I had tried: (in config/initializer/carrierwave.rb)
CarrierWave.configuration do |config|
config.assets_host = "http://assets.lvh.me:3000"
end
But when I try this setting then the rails popup an error message:
undefined method `assets_host=' for CarrierWave::Uploader::Base:Class (NoMethodError)
Since the README of carrierwave has this description of setting but only in fog section, so I'm wondering that is this function only work while using fog? Or did I miss anything?
Thanks for help
should use asset_host ( version > 0.7.0)
see chnage commit on github
https://github.com/jnicklas/carrierwave/commit/7046c93d6b23cffef9f171a5f7f0dd14267a7057#lib/carrierwave/uploader/configuration.rb
CarrierWave.configuration do |config|
config.asset_host = "http://assets.lvh.me:3000"
end
In later versions this changed to
CarrierWave.configure do |config|
...
end
Related
In production, when I call image_tag inside a mailer view, the image url reflects the asset host that I've set. However, when I call ActionController::Base.helpers.image_tag in a module inside lib/ it does not reflect the asset host.
This is in the production environment.
production.rb
config.action_mailer.asset_host =
config.action_controller.asset_host = Proc.new do |source|
"https://mycustomhost.com"
end
production console:
irb(main):001:0>
ActionController::Base.helpers.image_tag("my_asset.jpg")
=> ...src=\"/my_app/my_asset-b00c676835d609cc1aed3ce6e7018ee1.jpg\"..
Documentation suggests that I need to set the asset_host on ActionController::Base. I've tried both setting setting ActionController::Base.asset_host in the console/setting it in production.rb and restarting nginx, then running ActionController::Base.image_tag, but it still does not return the image url with the asset host.
Any ideas what's going on?
I got this to work by getting view_context from the mailer, and calling the helper method on that. It doesn't explain why ActionController::Base.helpers.image_tag isn't reading from asset_host though, but since I'm essentially trying to replicate the behavior of ActionView's image_tag, this approach seems better.
I am using rails 4.1.1 and ActionMailer::Preview for previewing emails. In development environment everything is working excellent.
But in production environment the preview routes are not accessible. I store the previews in test/mailers/previews/
Is is possible to enable them for production?
In addition to this:
config.action_mailer.show_previews = true
you will also need to set
config.consider_all_requests_local = true
in your environment for the preview routes to be accessible. This has other implications as well (see https://stackoverflow.com/a/373135/1599045) so you likely don't want to enable this in production. However, if you have a custom environment that's not development, the combination of those two should get things working.
EDITED TO ADD:
The original question was for rails 4.1.1, which doesn't have config.action_mailer.show_previews available. To get ActionMailer previews working in non-development environments in rails 4.1.1, you need to first add some routes to config/routes.rb (in this case, my environment is named custom):
if Rails.env.custom?
get '/rails/mailers' => "rails/mailers#index"
get '/rails/mailers/*path' => "rails/mailers#preview"
end
Then you need to autoload the libraries needed in your environment's config file (in my case, config/environments/custom.rb):
config.action_mailer.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/test/mailers/previews" : nil
config.autoload_paths += [config.action_mailer.preview_path]
This seems to perform the same task as config.action_mailer.show_previews does.
As with 4.2, you will still need to adjust the local request configuration as above depending on whether your custom environment is being used locally or on a server.
To do it without opening a big security hole:
production.rb
MyApp::Application.configure do
config.action_mailer.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/spec/mailer_previews" : nil
config.autoload_paths += [config.action_mailer.preview_path]
routes.append do
get '/rails/mailers' => "rails/mailers#index"
get '/rails/mailers/*path' => "rails/mailers#preview"
end
end
class ::Rails::MailersController
before_filter :authenticate_admin!
def local_request?
true
end
private
def authenticate_admin!
...
end
end
It's possible to enable previews in production by config.action_mailer.show_previews = true as the best answer says.
I just want to add how you can render previews in iframe within your own admin area, eg. in active admin (Rails 5.1)
And also I found out that it is not so hard to write your own email previews administration, and don't use rails standard previews at all. You can then add your own features such as changing preview parameters or Send button to see this email in your phone.
From Rails 4.2 you can use the flag in production.rb (or other custom enviroment):
config.action_mailer.show_previews = true
I haven't found anything similar in Rails 4.1.
Update:
If Rspec used, for example, there will be need to add the path:
config.action_mailer.preview_path = "#{Rails.root}/spec/mailers/previews"
Default path is "#{Rails.root}/test/mailers/previews".
And no need to touch config.consider_all_requests_local
Here's what I did for Rails 5.2:
production.rb
config.action_mailer.show_previews = true
config.action_mailer.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/spec/mailers/previews" : nil
class ::Rails::MailersController
include ::ApplicationController::Authorization
before_action :require_admin
end
Assuming your ApplicationController::Authorization module has the code for require_admin. I preferred this approach rather than rewriting my authorization code. Remembering to include the :: in front was tricky, because saying include ApplicationController::... will look within the Rails::MailersController namespace.
I'm trying to write an integration test that involves a file uploaded with Carrierwave. I have the following configuration:
CarrierWave.configure do |config|
if Rails.env.test?
config.storage = :file
config.enable_processing = false
else
# other configs
end
end
And my uploader has the store path set to:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
The outcome of this is that the file gets stored in public/uploads. But when I try to access this file via the doc.url method on my model, it returns a path like /uploads/..., and when running my integration specs I get the following error:
unable to open file `/uploads/doc/paper/1/img_1.png'
I can confirm that the file does exist in the /public/uploads directory. How do I get the Carrierwave to return the correct path to the uploaded image? I could patch it together with Rails.root.join('public', doc.url) but that would break in production where we're uploading to S3.
After investigating it some more I realized that the problem here is that we are trying to access the file server side. Client side everything works fine, because it's using relative paths and Rails resolves it as an asset path. Server side it doesn't know where to look. In dev and production we use S3 so the url is the same either way. It feels like a bit of a hack, but where we need to access the image on the server, we did this:
path = Rails.env.test? ? doc.img.path : doc.url
file = File.open(path)
I wasn't able to find an environment agnostic way to handle this.
I see this error:
undefined method `root' for AWS::Rails:Module
The corresponding line in my controller:
directory_name = Rails.root.join('public', #curAdmin.name)
This worked fine until I recently added the aws-sdk gem to my application to push static files and assets over to my S3 bucket.
Now it seems like when I call "Rails" the application thinks I'm referring to an AWS class method.
I don't know how I tripped the system up to do this.
This will happen if you refer to Rails within the AWS namespace. You should be able back out of the namespace by prepending :: to the module - ie ::Rails.root.join('public', #curAdmin.name)
I don't know why I tripped everything up - but if I remove the include at the top of the controller:
#include AWS
And then I refer to such methods directly as:
s3 = AWS::S3.new
bucket = s3.buckets['my_bucket_here']
It works ok. I'd still like to know what I did wrong.
I am using premailer, and on my local machine I get links like this in the mail notes:
file://localhost/assets/header_logo.png
instead of
http://localhost:3000/assets/header_logo.png
How do I configure premailer so that the url is correct while in development?
I tried adding
Premailer::Rails.config.merge!(base_url: "http://localhost:3000")
to my development config file, but the server barfs saying there is no method Premailer::Rails.config.
I also did this:
config.action_mailer.default_url_options = {:host => 'localhost:3000'}
to no avail...
So the problem was that I was still using the premailer-rails3 gem, but reading the premailer-rails doc. Just updating the gem to premailer-rails fixed the issue.
For the archives... you can also put this into say config/initializers/premailer.rb and it will pick up whatever you've set for ActionMailer...
Premailer::Rails.config.merge!(
:base_url => "http://#{ActionMailer::Base.default_url_options[:host]}"
)