What is wrong with my heroku asset:compilation? - ruby-on-rails

I am trying to insert an image into a mailer, everything runs locally but heroku doesn't see the image on its server despite pushing and precompiling as I'm ought to do. Code as below;
user_mailer.rb
def welcome_email(user)
#user = user
attachments.inline['my_logo_sml.png'] = File.read('app/assets/images/my_logo_sml.png')
mail(to: #user.email, subject: 'Welcome to Mybiz')
end
welcome_email.html.erb
<td class="six sub-columns header_logo">
<%= image_tag attachments["my_logo_sml.png"].url -%>
</td>
gemfile
gem 'rails_12factor', group: :production
app/assets/images/my_logo_sml.png is clearly present and getting through the pipline locally.
I have run RAILS_ENV=production bundle exec rake assets:precompile a number of times, I have heroku restart'ed a number of times.
Heroku logs:
2015-06-03T22:38:50.824191+00:00 app[web.1]: Errno::ENOENT (No such file or directory # rb_sysopen - app/assets/images/my_logo_sml.png)
I'm at a loss after hours going round and around on this, can anyone help me please?
Update
After hours of looking at this i feel like it's not a syntax issue but an asset pre-compilation issue of some sort, I've copied my config/environments/production.rb code below if anyone can spot anything wrong?:
Rails.application.configure do
config.cache_classes = true
config.eager_load = true
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
config.assets.js_compressor = :uglifier
config.assets.compile = true #concerned that this is the right thing to do?
config.assets.digest = true
config.log_level = :debug
config.i18n.fallbacks = true
config.active_support.deprecation = :notify
config.log_formatter = ::Logger::Formatter.new
config.active_record.dump_schema_after_migration = false
config.action_mailer.asset_host = 'http://mysite.co'
ActionMailer::Base.smtp_settings = {
:address => 'smtp.sendgrid.net',
:port => '587',
:authentication => :plain,
:user_name => ENV['SENDGRID_USERNAME'],
:password => ENV['SENDGRID_PASSWORD'],
:domain => 'heroku.com',
:enable_starttls_auto => true
}
end
Perhaps I could clean all compiled assets out and start the whole thing again, could anyone advise as to how to do this?
Update
The source of my problem seemed to be confusion between local and slug asset compilation. I ran heroku run rake assets:clobber and this solved all of my problems. Full understanding of what precisely was going on still eludes me, however running the above and having config.assets.compile = true in config/environments/production.rb has everything working just fine and upon git push heroku it shows me clearly that it's running both rake assets:clean and rake assets:precompile just fine. Syntax used in the view was:
welcome_email.html.erb
<%= image_tag('my_logo_sml.png', alt: "My Logo Small")%>
I'm still unsure as to whether having config.assets.compile = true is the correct thing to do despite it seeming to solve the problem, i wonder whether it might end up compiling assets on multiple occasions?

I had similar problem. I think welcome_email.html.erb file can not be .erb file. There is a workaround. You can put image somewhere on the web like Amazon or Image share services and use link as source.
<img src='https://example.com'>

Reading the file from Rails console as suggested by #user123 shows that the paths are correct and the file is there. Trying to reading the file from Heroku run console does not find the file and comes up with the same Errno::ENOENT no such file error Strangely heroku is serving an image in the homepage which i try to load as described above in heroku console and it is unable to find it.

Related

Rails Mailer not working in production on website, but works in console

I'm banging my head against a wall.
So here is my problem. Let's start really simple. I have a contact form in my app, it sends emails after clicking submit. This form works perfectly in development mode. But for some unknown reason it does not work in production.
Well, what would you do now? Check production.rb in config/environments? Already done. Actually more than that - I have tried sending a mail with the rails console in production mode on my VPS. And it works.
UserMailer.send_data(Deliverer.new(full_name: "John Smith", email: "john.smith#yahoo.com", message: "Hello how are you")).deliver_now
I have a model called Deliverer, purely for antispam purposes. After entering the rails console in production on my server and pasting this command, a mail gets sent to my mailbox, just as it is supposed to work from the website.
This is my production.rb file
require "active_support/core_ext/integer/time"
Rails.application.configure do
config.cache_classes = true
config.eager_load = true
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present?
config.assets.compile = true
config.active_storage.service = :local
config.force_ssl = true
config.action_mailer.default_url_options = { host: ENV['DOMAIN'] }
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
port: '465',
address: 'smtp.seznam.cz',
domain: ENV['DOMAIN'],
user_name: ENV['SMTP_USERNAME'],
password: ENV['SMTP_PASSWORD'],
authentication: :plain,
enable_starttls_auto: true,
ssl: true,
tls: true
}
config.log_level = :info
config.log_tags = [ :request_id ]
config.action_mailer.perform_caching = false
config.i18n.fallbacks = true
config.active_support.report_deprecations = false
config.log_formatter = ::Logger::Formatter.new
if ENV["RAILS_LOG_TO_STDOUT"].present?
logger = ActiveSupport::Logger.new(STDOUT)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
end
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
end
This is the SMTP error that I found in /log/production.log
Net::SMTPFatalError (550 5.7.1 Not authenticated, please use AUTH first.
As I said, this error shows up only in production when trying to send the mail from the website. Sending an email from the console on production works, the form from the website does not. And as I said, everything works fine in development, both the console and the form itself.
And I have no idea what to do.
TL:DR The mailer works in development mode (both from the website and with the rails console). In production, the mailer works only in rails console, but not from the website.
Mailer in production after submitting the form from the website does not work, but works fine when using the rails console. No problems at all in development.
Okay, I've managed to solve this problem.
For some unknown reason, Rails was failing to recognize ENV[] variables. I really don't know why.
But once I replaced ENV['SMTP_USERNAME'] with "username#domain.com" and ENV['SMTP_PASSWORD'] with "examplepassword" it all started working and mailer sends emails to my inbox.
I got no idea, because entering rails console or irb and using
puts ENV['SMTP_USERNAME']
actually printed my smtp username, the exact same thing happened with password and other environmental variables. I got no idea what was wrong.
EDIT
Okay I've done a little bit of troubleshooting. It seems like only config/environments/production.rb has a problem with accessing ENV variables. I'm not sure why...

Assets url Rails 4.1 and Heroku

Something always seems to go wrong when deploying an app to heroku, today its my images not being rendered.
I ran
rake assets:precompile RAILS_ENV=produciton
committed changes and pushed to heroku
In my view for example i have
<%= image_tag('/assets/logo.png') %>
but the image is not being rendered because its looking for logo.png as opposed to
logo-321321327454547676576586876.png
which was generated when running the precompile.. I think im missing an option in my production.rb file somwhere
Rails.application.configure do
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
config.serve_static_assets = false
config.assets.js_compressor = :uglifier
config.assets.compile = false
config.assets.digest = true
config.assets.version = '1.0'
config.log_level = :info
config.active_support.deprecation = :notify
config.log_formatter = ::Logger::Formatter.new
config.active_record.dump_schema_after_migration = false
end
How do i get the app to look for the generated image url created when precompiling? something simple Im guessing
I am going to use an S3 bucket to serve these in the future but am interested in getting it working with Heroku on its own
Thanks
After reading the api docs in more detail and taking Baloo's advice the answer is really simple, just a syntax issue with my path declarations
If your image is under assets just use
<%= image_tag('image.ext') %>
and if its in a sub directory then use
<%= image_tag('sub-dir/image.ext') %>
Hope this helps someone else

Rails 4.1 and exception_notification-rake gem causing uninitialized constant ExceptionNotification

I've upgraded to Rails 4.1 and am trying to set up the exception_notification-rake gem to notify me by email of failed rake tasks.
In my Gemfile, I have gem 'exception_notification-rake'.
In development.rb, I have the following:
MyApp::Application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Do not eager load code on boot.
config.eager_load = false
# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
# Specify what domain to use for mailer URLs
config.action_mailer.default_url_options = {host: "localhost:3000"}
config.action_mailer.smtp_settings = {
:address => 'smtp.gmail.com',
:port => 587,
:domain => 'gmail.com',
:user_name => Rails.application.secrets.email['user'],
:password => Rails.application.secrets.email['pass'],
:authentication => 'login',
:enable_starttls_auto => true
}
# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log
# Raise an error on page load if there are pending migrations
config.active_record.migration_error = :page_load
# Debug mode disables concatenation and preprocessing of assets.
# This option may cause significant delays in view rendering with a large
# number of complex assets.
config.assets.debug = true
config.after_initialize do
Bullet.enable = true
Bullet.alert = true
Bullet.bullet_logger = true
Bullet.console = true
# Bullet.growl = true
Bullet.rails_logger = true
Bullet.add_footer = true
end
config.middleware.use ExceptionNotification::Rack,
:ignore_if => lambda { |env, exception| !env[:rake?] },
:email => {
:sender_address => %{"notifier" myemail#gmail.com},
:exception_recipients => %w(myemail#gmail.com)
}
ExceptionNotifier::Rake.configure
end
As you can see, I'm passing in the user and password using Rails 4.1's secrets.yml file.
When I try starting up my Rails server, I get the following error:
/development.rb:52:in `
block in <top (required)>': uninitialized constant ExceptionNotification (NameError)
I'm guessing this is a bug in the exception_notification-rake gem which calls a previous version of the exception_notification, but I'm not sure. Any help with this would be appreciated!
Thanks :)
Update:
I've notified the exception_notification-rake gem developer about this. I have all the prerequisite gems and have a fairly vanilla setup so I think this might be a bug that needs to be fixed for Rails 4.1
As can be seen in this issue the current, published, version of ExceptionNotification does not work with rails 4.1
Until the new version is released, you can just use the master version. In your Gemfile include your gem as follows:
gem 'exception_notification', github: 'smartinez87/exception_notification'
The maintainer has released a rc-version, which you can use as follows
gem 'exception_notification', '4.1.0.rc1'
Once the new gem version is released, you can switch to the released version (4.1.0). This should not take too long I guess ;)

Rails / Devise / Mailer: Throwing 'config.action_mailer.default_url_options' error on attempted registration

It's just been one problem after another today. I just deployed to my production server and testing it out, with issues whenever anything involves email. Particularly with Devise's confirmable registration email, whenever I sign up for an account, the following error is thrown up in the log...
ActionView::Template::Error (You can no longer call ActionMailer::Base.default_url_options directly. You need to set config.action_mailer.default_url_options. If you are using ActionMailer standalone, you need to include the routing url_helpers directly.):
Looking at my config/environments/production.rb, I have the following set...
config.action_mailer.default_url_options = { :host => 'localhost' }
So config.action_mailer.default_url_options IS being used, but is being completely ignored. I tried changing the host to '127.0.0.1' and my server's IP addy, but it wouldn't have it. Threw it in config/application.rb, but no go. I hunted in my project for any other lines declaring default_url_options, but it's only set in the production.rb file. I Googled and found a post suggesting to set config.cache_classes to false, but negative there as well.
Now here is what's crazy...I got the same error whenever I tried to submit a brand new comment in my project (set up to send an email to confirm the email address if you are a first time commentor). I took OUT config.action_mailer...etc from the production.rb file, and viola - my comment mailer worked and sent the email just fine!
Still, Devise is being absolutely stubborn and keeps throwing the above error at me. Any ideas on why? BTW, all my gems are up to date. Below is my production.rb file.
--- UPDATE ---------------
Have made a little progress, but this is just weird. When I start the server and attempt to do something that will send mail (user registration, comment), I get the ActionMailer::Base error message above. When I try the action AGAIN...it works and the mail gets sent. From that point on (until Passenger and/or the server is rebooted), all mailer actions work fine.
But not without yet another issue (it never ends)...for some reason the email body is completely blank.
I ended up hitting this problem once again when I attempted to test in the test database, and I was determined once and for all to figure out why I was getting this error, and why no one else seemed to have come across it (very little results from Google).
After completely tearing down my project and reconstructing it, I finally pinpointed the issues to the Sitemap-generator plugin I had installed. Once I removed all traces of that, the above error finally ceased.
I'm working on this issue for Fat Free CRM, and I realized that this error happens because Rails 3 lazy-loads classes. All you need to do is 'touch' the ActionMailer::Base class in your environments/**.rb files, and it will load the class. Then you can call ActionMailer::Base.default_url_options from a controller, etc. (We do this so that we can automatically set the mailer host from request.host_with_port)
So my environment files now look like this:
FatFreeCRM::Application.configure do
...
ActionMailer::Base
end
I believe I have solved this issue...though I'm not "exactly" sure what did it. It very well may have been config.cache_classes = true which I commented out, and although I was concerned this would effect my site caching or something else, it doesn't seem to have broke it.
In addition, the empty email body I solved by switching from :sendmail to :smtp.
Here is my final production.rb file, hopefully this might be of use to someone with a similar issue in the future.
MyProject::Application.configure do
# Commented out, causes 'ActionView::Template' error
#config.cache_classes = true
config.whiny_nils = true
config.consider_all_requests_local = true
config.action_view.debug_rjs = true
config.action_controller.perform_caching = true
config.cache_store = :mem_cache_store
config.active_support.deprecation = :log
config.action_dispatch.best_standards_support = :builtin
config.action_mailer.raise_delivery_errors = true
Sunspot.config.solr.url = 'http://127.0.0.1:8080/solr'
Paperclip.options[:command_path] = "/usr/bin/"
config.action_mailer.perform_deliveries = true
config.action_mailer.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:enable_starttls_auto => true,
:port => 587,
:authentication => :plain,
:user_name => "user#domain.com",
:password => 'password'
}
config.action_mailer.default_url_options = { :host => 'dev.mydomain.com' }
config.time_zone = "Central Time (US & Canada)"
end

Problem running RoR app in production environment

Have an app that has "listings" - think classified ads - and each listing has a list of tags.
The following code fails when I run the app in production mode, but works fine under development mode
uninitialized constant ActiveRecord::Acts::Taggable::InstanceMethods::TagList
Extracted source (around line #45):
42:
43: <span class="listingIndexTags">
44: Location: [location] | Tags:
45: <% tag_list = listing.tag_list %>
46: <% if tag_list != nil %>
47: <% for tag in tag_list %>
48: <%= link_to tag.to_s, { :action => "filter_on",
The command line I'm using to start my mongrel instance in this test case:
ruby script/server mongrel -e production
Defaults to port 3000. I can access other views in the app that DON'T call "listing.tag_list".
".tag_list" is provided by "acts_as_taggable_on_steroids", which I'm using in this app. It is installed as a gem.
Maybe my environment files are wonky?
Here's my development.rb file
config.cache_classes = false
config.whiny_nils = true
config.action_controller.consider_all_requests_local = true
config.action_view.debug_rjs = true
config.action_controller.perform_caching = false
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
...took these settings out for this post...
}
And my production.rb file...
config.cache_classes = true
config.threadsafe!
config.action_controller.consider_all_requests_local = false
config.action_controller.perform_caching = true
config.cache_store = :mem_cache_store
config.action_mailer.raise_delivery_errors = false
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
...took these settings out for this post...
}
FIXED:
Well, after putting off fixing this bug until I absolutely had to (today), I at long last found the source of the issue.
The inclusion of the line:
config.threadsafe!
In my "production.rb" file was causing it.
I finally found it by:
1. Making my production and development environment files identical
2. Line-by-line, changing the production environment file until it either:
a. The app broke in production mode
b. I was back to my original production file
Anyhow, when I got to adding the "config.threadsafe!" line - IT BROKE! I was never so happy to have an app break.
So, a little reading to understand what exactly this option does, in conjuction with Mongrel (if Mongrel is even relevant), and I'll have my answer.
Came along here with the same problem and just wanted to hand a note to everyone experiencing the same....I've managed to sort this problem this by fixing the version of gems in environment.rb
changed this
config.gem "acts-as-taggable-on", :source => "http://gemcutter.org"
to this:
config.gem "acts-as-taggable-on", :source => "http://gemcutter.org", :version => '2.0.0.rc1'
and run a rake gems:install
I wonder if you somehow were running different gems on different environments if that is possible.
Do you have the acts_as_taggable_on_steroids gem installed on your production server?

Resources