Use constant declared in Initializer in Environment.rb - ruby-on-rails

Essentially what I want to do is keep my email username and password in a separate file to my environment.rb I've used the initializers in other places to do this - but here the environment seems to be loaded first:
development.rb
config.action_mailer.smtp_settings = {
:address => "smtp.example.com",
:port => 587,
:domain => "www.example.com",
:authentication => "plain",
:user_name => SMTP_USERNAME,
:password => SMTP_PASSWORD,
:enable_starttls_auto => true
}
When I start my Rails server I get an error:
uncaught exception: uninitialized constant SMTP_USERNAME
Would this be a scoping issue of due to the fact that the constants in the Initializers are declared after the environment, and what can I do about it?

What if you try defining your constants in application.rb, inside class Application < Rails::Application? You might then access the constants by doing something like Application::SMTP_USERNAME. That's just a guess.

Related

Missing host to link to Rails heroku production

I have an app that I am trying to put onto production. When the user signs up they have an activation email that should be sent to their email accounts but I am getting stopped with this error:
ActionView::Template::Error(Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true)
The problem with this error is that I have everything set up correctly in my files. For example my production.rb file inside my environments folder looks like this:
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.default_url_options = { :host => 'secret-everglades-54128.heroku.com'}
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
}
My enviorments.rb file looks like this:
# Load the Rails application.
require_relative 'application'
# Initialize the Rails application.
Rails.application.initialize!
config.action_mailer.default_url_options = { :host => 'secret-everglades-54128.heroku.com'}
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
This does not make any sense to me whatsoever, if anyone could shed some light on this problem I will be very great full.
The problem was that I had errors still concuring when I ran the command
git push heroku master
The problem was that I had my host set in the actually environment.rb file which wasn't needed so I removed that and once I did that I was able to get everything to work.

Rails 4 action_mailer host

For Rails 4, I am using config.action_mailer.asset_host = "http://localhost:3000" in
config > environments > development.rb
to load assets to my mailer.
Is there a better value than a hardcoded url? I imagine there should be one since I would not use this value in my production.rb. What is the code to find the current host url in rails config?
If you deploy to a known host, you can put it directly in production.rb
But if you really need to read it from the url, than you check this out
http://api.rubyonrails.org/classes/ActionDispatch/Request.html#method-i-original_url
If you're using SendGrid, inside config/environment.rb file specify your ActionMailer settings to point to SendGrid’s servers.
ActionMailer::Base.smtp_settings = {
:user_name => 'your_sendgrid_username',
:password => 'your_sendgrid_password',
:domain => 'yourdomain.com',
:address => 'smtp.sendgrid.net',
:port => 587,
:authentication => :plain,
:enable_starttls_auto => true
}

Load rails app config from database

I'd like to load some config settings from the database when my Rails (3.2.13) app starts:
class MyApp < Rails::Application
#...normal config here...
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:address => SystemSetting.system_smtp_host,
:port => SystemSetting.system_smtp_port,
:user_name => SystemSetting.system_smtp_username,
:password => SystemSetting.system_smtp_password,
:authentication => SystemSetting.system_smtp_authentication,
:enable_starttls_auto => SystemSetting.system_smtp_enable_starttls_auto }
end
But it appears that the database config has not been read at this point. I get an error:
ActiveRecord::ConnectionNotEstablished (ActiveRecord::ConnectionNotEstablished)
How can I accomplish this? Either make Rails initialize the database config first, or ... something else?
Regarding practices: Doing stuff like this can be problematic because your application relies on your database to be full when in fact it should support an empty database. Two examples that I can think of are when you try to create a database from scratch (e.g. rake db:setup), or in tests environments.
However, if have no other choice: I would move the mailer initialization to your system_setting.rb or an initializer (where you are guaranteed to have a connection).
config/initializers/load_system_settings.rb
MyApp::Application.config.action_mailer.raise_delivery_errors = true
MyApp::Application.config.action_mailer.delivery_method = :smtp
MyApp::Application.config.action_mailer.smtp_settings = {
:address => SystemSetting.system_smtp_host,
:port => SystemSetting.system_smtp_port,
:user_name => SystemSetting.system_smtp_username,
:password => SystemSetting.system_smtp_password,
:authentication => SystemSetting.system_smtp_authentication,
:enable_starttls_auto => SystemSetting.system_smtp_enable_starttls_auto
}
Manually connect and load values from database.
class Application < Rails::Application
# Set your app path
app_base = 'MY_APPLICATION_PATH'
# Load db configs
db_yml = YAML.load_file("#{app_base}/config/database.yml")["production"]
# Establish db connection
ActiveRecord::Base.establish_connection(:adapter=>db_yml['adapter'], :database=>db_yml['database'], :username=>db_yml['username'], :password=>db_yml['password'])
# load model if not
require "#{app_base}/app/model/system_setting.rb" unless defined?('SystemSetting')
#...normal config here...
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:address => SystemSetting.system_smtp_host,
:port => SystemSetting.system_smtp_port,
:user_name => SystemSetting.system_smtp_username,
:password => SystemSetting.system_smtp_password,
:authentication => SystemSetting.system_smtp_authentication,
:enable_starttls_auto => SystemSetting.system_smtp_enable_starttls_auto }
#close sql connection after loaded
ActiveRecord::Base.connection.close
end

Devise email confirmation from localhost

I am able to get the registration confirmation email to send out in deployment on Heroku, but when I try a registration on localhost:3000, I get the following error:
undefined local variable or method `confirmed_at' for #<User:0xb67a1ff0>
In my config/environments/production.rb file I have:
config.action_mailer.default_url_options = { :host => 'xxxx.com' }
And I have an initializer file with the following format:
ActionMailer::Base.smtp_settings = {
:user_name => "xxxx#heroku.com",
:password => "xxxxxx",
:domain => "xxxx.com",
:address => "smtp.sendgrid.net",
:port => "xxx",
:authentication => :plain,
:enable_starttls_auto => true
};
What settings do I need to get the localhost working?
Thanks!
John
Is your local environment migrated? Does your user model have :confirmable in the devise call? Does User.confirmed_at exist in your database (do you have any pending migrations)?
You should also probably add a stacktrace from your exception if you have one.
Sounds like you're missing a confirmed_at field for your user model.
You may correlate this with your schema.rb file.

Why wouldn't a specific environment override environment.rb in rails here?

I'm trying to work on a Rails site here in it's development environment, where I want to test email delivery, and I can't work out why properties declared in the main environment.rb aren't being overwritten by the more specific development.rb file that I presume would be loaded when booting a rails app.
My understanding here is that values in more specific environment config files like this should override the shared 'environment.rb' config file, so if I have declared some email settings like so in config/environment.rb...
ActionMailer::Base.smtp_settings = {
:address => 'smtp.hostingcompany.com',
:port => 25,
:domain => 'productiondomain.net',
:authentication => :login,
:user_name => "productiondomainmailer",
:password => "TOP_SEKRIT"
}
... then code here in config/environments/development.rb below should override the ActionMailer:Base.smtp_settings hash:
ActionMailer::Base.smtp_settings = {
:domain => 'developmentdomain.net'
}
However, when load the app in the development environment, or from script/console to check the value of ActionMailer::Base.smtp_settings[:domain], it's still listed as 'productiondomain.net'.
Why might this happening?
To set the configuration for your development environment put:
config.action_mailer.smtp_settings =
rather than:
ActionMailer::Base.smtp_settings =
in config/environments/development.rb
Note that in config/environments/development.rb you will need to specify the full set of settings and not just :domain as the hash overwrites the existing value rather than being merged with it.
And similarly, set the default in config/environments.rb by putting config.action_mailer.smtp_settings = inside the Rails::Initializer.run do |config| block.
This should work:
config.action_mailer.smtp_settings = {
:address => 'smtp.some_host.com',
:port => 25,
:domain => 'developmentdomain.net',
:authentication => :login,
:user_name => 'blabla',
:password => "some_pass"
}

Resources