NoMethodError: undefined method `const_defined?' when referring to class methods - ruby-on-rails

I am building an email sending system into an already fairly complex rails app.
From a controller I'm trying to call a method that builds an email and then delivers it.
In controller:
response_for :create, :update do
estimate = current_object.estimate.reload
flash[:success] = "Tier Save Successful. "
flash[:success] += send_estimate_email if estimate.verify && estimate.tiers.select{|t| !t.verified?}.empty?
flash[:notice] = "This service bundle was changed for a previously verified service bundle. Please re-verify after changes are complete" if current_object.auto_unverified
redirect_to [current_object.estimate]
end
def send_estimate_email
return "" if current_object.estimate.requestor_email.blank? || !current_object.estimate.requestor_notified_at.blank?
begin
estimate = current_object.estimate
host = request.host_with_port
binding.pry
success = EstimateEmailer.deliver_verification_complete(estimate, host)
current_object.estimate.notes.create!(:user_id => User.find(:first, :conditions => {:user_type_id => UserType::ROOT.id}).id, :title => "Verification Complete Email Sent", :body => "TO: #{success.to}\nSUBJECT: #{success.subject}\nBODY: #{success.body}")
rescue Exception => e
logger.warn(e)
success = false
end
if success
current_object.estimate.update_attribute(:requestor_notified_at, Time.now)
current_object.estimate.notes.create!(:title => "Auto-email sent to requestor", :body => "TO: #{success.to}\nSUBJECT: #{success.subject}\nBODY: #{success.body}", :user_id => current_user.id)
return "Automatic estimate email was successfully sent to #{current_object.estimate.requestor_email}"
else
return "However, automatic estimate email could not be sent due to an error"
end
end
I don't think there's anything wrong with the email code itself, but for some reason I get this error on the EstimateEmailer.deliver_verification_complete(estimate, host) call:
NoMethodError: undefined method `const_defined?' for "estimate":String
setting a breakpoint in the controller before the EstimateEmailer call I notice that I get the error whenever I try to refer to other classes. Just calling EstimateEmailer or any other class name returns the same error.
I've run into issues with undefined method const_defined? in the past. I'm guessing the issue isn't specific to emailing, but I haven't the slightest idea where to begin debugging.
def verification_complete(estimate, host)
request_id = estimate.integration_transactions.empty? ? "Internal ID #{estimate.id}" : estimate.integration_transactions.last.source_id
#estimate = estimate
#estimate_url = public_estimate_url(estimate.public_id, :host => host, :protocol => 'https')
mail(
subject: "Ref ##{estimate.project_code} Application Hosting Estimate Available for Review: #{request_id}",
to: [estimate.requestor_email, estimate.project_manager_email].reject{|email| email.blank? }.join(','),
from: SUPPORT_ADDRESS
)
end

You're using make_resourceful which has an incompatibility with current versions of ActiveSupport. I've just lodged a PR that addresses it: https://github.com/hcatlin/make_resourceful/pull/16.
Alternatively, you can point to the remote branch in your Gemfile:
gem 'make_resourceful', github: 'carpodaster/make_resourceful', branch: 'fix/incompatibility-with-active-support-dependencies'
I assume this problem only occurs in your development environment, right? In that case, you should be able to avoid it by setting config.eager_load = true in config/environments/development.rb.

Related

Pushmeup Gem - Can't send push notifications in Active Admin model

I'm creating a CRM/CMS in Rails using Active Admin.
I've used Pushmeup Gem for the APNS(Apple Push notification service) functionality but I can't seem to make it work.
Here's what I did.
Forked the Pushmeup Gem to create my own repository. I've edited the configurations to match my credentials.
gem 'pushmeup', :git => 'git://github.com/thisisnotme/pushmeup.git'
I've followed the instructions here.
Here's my app/admin/token.rb file.
collection_action :apns, method: :get do
device_token = '7eb2c5fa7f3b0be45cb3613b1d05470c5b76b90929a8ce49d2e511d7b1245d8a'
APNS.send_notification(device_token, 'Hello iPhone!' )
APNS.send_notification(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default')
end
This came up on my screen:
NoMethodError in Admin::DeviceTokensController#apns
undefined method `close' for nil:NilClass
Extracted source (around line #19):
17
18
19
20
21
22
collection_action :apns, method: :get do
device_token = '7eb2c5fa7f3b0be45cb3613b1d05470c5b76b90929a8ce49d2e511d7b1245d8a'
APNS.send_notification(device_token, 'Hello iPhone!' )
APNS.send_notification(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default')
end
It seems that the APNS class is missing. I'm kinda lost. Sorry Rails Newbie.
I've found that the host and port are defined as follows:
module APNS
#host = 'gateway.sandbox.push.apple.com'
#port = 2195
class << self
attr_accessor :host, :pem, :port, :pass
end
end
So you just can redefine APNS variables, as it is shown in the README:
APNS.host = 'gateway.push.apple.com'
APNS.port = 2195
APNS.pem = '/path/to/pem/file'
APNS.pass = ''
Maybe this is kinda late but I had the same error. It was thrown because I did not extract the certificate AND the key from the keychain into a single PEM file.

Rails 3.2.14: ActionMailer fails to find template in production only

We have a Rails 3.2.14 app that is misbehaving in production only. Emails fail to send with the following error message:
ActionView::MissingTemplate (Missing template /invoice with {:locale=>[:en], :formats=>[:text], :handlers=>[:erb, :builder]}. Searched in:
* "/var/www/appname/releases/20131003214241/app/views"
):
app/mailers/mailer.rb:42:in `block in invoice'
app/mailers/mailer.rb:41:in `invoice'
app/controllers/admin_controller.rb:410:in `resend_invoice'
The Mailer#invoice method looks like this:
def invoice(order, resent=false, receipt_or_invoice = "Receipt")
#order = order
#freebie = #order.freebie?
#mail = true
#transaction = #order.beanstream_transaction
#user = #order.user
recipient = #order.email_receipt_to || #user.email || "support#example.com"
#receipt_or_invoice = receipt_or_invoice
subject = #freebie ? "Your License" : "Your #{receipt_or_invoice.capitalize} and License Information#{ resent ? " (Resent)" : ""}"
mail = mail(:to => [recipient], :subject => subject)
mail.add_part(Mail::Part.new do
content_type 'multipart/alternative'
# THE ODD BIT vv
mail.parts.reverse!.delete_if {|p| add_part p }
end)
mail.content_type 'multipart/mixed'
mail.header['content-type'].parameters[:boundary] = mail.body.boundary
#order.line_items.each do |li|
aq_data = li.license.aquatic_prime_data
if aq_data.present?
attachments[li.license.aquatic_prime_filename] = {content: aq_data, mime_type: 'application/xml'}
end
end
return mail
end
A couple notes.
This behaves fine in development using Pow. Production is using Apache+Passenger.
Before this, the last change we made to our mailer was in June to add a new method. We've seen no other reports about failure to deliver emails. This makes me think something changed in the ActionMailer or other Rails gem that somehow caused this issue.
The error also happens when Mailer.invoice is called from our store controller or other part of the code, so I think it's localized to the Mailer.
In development, we're using Google SMTP server for sending mail, whereas we're using Postmark in production.
Thanks in advance for any help or insights!
Turns out, if something seems very complicated, you're usually doing it wrong. I changed our Mailer#invoice method to be like this and it worked fine:
def invoice(order, resent=false, receipt_or_invoice = "Receipt")
#order = order
#freebie = #order.freebie?
#mail = true
#transaction = #order.beanstream_transaction
#user = #order.user
recipient = #order.email_receipt_to || #user.email || "support#example.com"
#receipt_or_invoice = receipt_or_invoice
subject = #freebie ? "Your License" : "Your #{receipt_or_invoice.capitalize} and License Information#{ resent ? " (Resent)" : ""}"
#order.line_items.each do |li|
aq_data = li.license.aquatic_prime_data
if aq_data.present?
attachments[li.license.aquatic_prime_filename] = {content: aq_data, mime_type: 'application/xml'}
end
end
mail(:to => [recipient], :subject => subject)
end
The key bit is to do the attachments before the mail method. Then the multipart/alternative stuff works fine and the attachments are handled properly.
We still had a problem with Postmark refusing to deliver our custom file extension attachment, but that's a separate issue. I don't know why all the machinations we were going through were gumming up our view template_path or why the problem wasn't manifesting in development, but there it is…

ActionMailer::Base::NullMail when trying exception_notification in development

I'd like to add the exception_notification gem to our app, however, this happens when I try to manually trigger a mail:
exception
# => #<ZeroDivisionError: divided by 0>
ExceptionNotifier::Notifier.exception_notification(request.env, exception)
# => #<ActionMailer::Base::NullMail:0x007fa81bc7c610>
ExceptionNotifier::Notifier.background_exception_notification(exception)
# => #<ActionMailer::Base::NullMail:0x007fa81bf58190>
In the above example, the console is at a breakpoint inside rescue_from Exception in the ApplicationController after a deliberate 1/0 in some controller.
I'm using delayed_job as well, but - no surprise - ExceptionNotifier::Notifier.background_exception_notification(exception).deliver does not spool anything.
I've already set config.consider_all_requests_local = false in development, but still exception_notification instantiates NullMail. In other parts of the app, mailers work just fine and use sendmail.
Any ideas what I'm doing wrong here? Thanks for your help!
Likely you are using an old version of the ExceptionNotifier and a newer version of ActiveMailer::Base. Not calling the mail command within the email functionality will result in the ActionMailer::Base::NullMail instance returned rather than a Mail instance.
From documentation:
class Notifier < ActionMailer::Base
default :from => 'no-reply#example.com',
:return_path => 'system#example.com'
def welcome(recipient)
#account = recipient
mail(:to => recipient.email_address_with_name,
:bcc => ["bcc#example.com", "Order Watcher <watcher#example.com>"])
end
end
I had my tests / rspec returning NullMail objects. the solution was simple, my code was:
def my_mail(foo)
mail(
to: to,
from: from,
subject: #sample_item.campaign_market.campaign.translation_for(language_id, 'sample_item_mailer.request_review.subject'),
content_type: "text/html"
)
#sample_item.update_attributes!({feedback_requested: true, review_requested_at: Time.now})
TrackingService::Event.new(#user, #user.market, 'sample_items', "request_review_email #{#sample_item.id}").call()
end
what's not immediately clear from the ruby docs is that you need to return the mail function,not just execute it. If you need to do something after building the mail object make sure you return the mail at the end. like so:
def my_mail(foo)
m = mail(
to: to,
from: from,
subject: #sample_item.campaign_market.campaign.translation_for(language_id, 'sample_item_mailer.request_review.subject'),
content_type: "text/html"
)
#sample_item.update_attributes!({feedback_requested: true, review_requested_at: Time.now})
TrackingService::Event.new(#user, #user.market, 'sample_items', "request_review_email #{#sample_item.id}").call()
return m
end

Troubleshooting Active Merchant returning "Failed with 500 Internal Server Error"

The following code
purchase = #order.authorize_payment(#credit_card, options)
is_success = purchase.success?
if is_success
...
else
flash[:notice] = "!! " + purchase.message + "" +
purchase.params['missingField'].to_s
redirect_to :action => :payment, :id => #order.id
end
results in "!! Failed with 500 Internal Server Error" in my flash[:notice]. There is no stacktrace, no webserver error, all that I know is that purchase.message is populated and purchase.success? is false.
I am really at a loss to figure out how to troubleshoot this. I think it might be an ssl requirement, but I can't either see the soap request, or test basic connectivity with cybersource (my payment gateway).
I establish my gateway with this code (after config.after_initialize do):
ActiveMerchant::Billing::Base.mode = :production # :test
ActiveMerchant::Billing::CreditCard.require_verification_value = false
ActiveMerchant::Billing::CyberSourceGateway.wiredump_device = File.new(File.join([Rails.root, "log", "cybersource.log"]), "a") # doesn't work (!)
# we need to open an external file to get the password
mypassphrase = File.open('/var/www/foo/shared/passphrase.txt').read
OrderTransaction.gateway = ActiveMerchant::Billing::CyberSourceGateway.new(:login => 'vxxxxxxx',
:password => mypassphrase.to_s,
:test => false,
:vat_reg_number => 'your VAT registration number',
# sets the states/provinces where you have a physical presense for tax purposes
:nexus => "GA OH",
# don‘t want to use AVS so continue processing even if AVS would have failed
:ignore_avs => true,
# don‘t want to use CVV so continue processing even if CVV would have failed
:ignore_cvv => true,
:money_format => :dollars
)
Can I see the soap request? Are there ways to test part of this? Any help greatly appreciated.
Best,
Tim
ActiveMerchant::Billing::CyberSourceGateway.logger = your_logger
So, late response but...
I've done a good amount of work with the Cybersource gateway, and the only way to see the SOAP request/response of the cybersource gateway currently is to open up the gem and edit it.
If you modify the commit method of lib/active_merchant/billing/gateways/cybersource.rb, you can do something like this:
def commit(request, options)
puts "*** POSTING TO: #{test? ? TEST_URL : LIVE_URL}"
request = build_request(request, options)
puts "*** POSTING:"
puts request
begin
post_response = ssl_post(test? ? TEST_URL : LIVE_URL, request)
rescue ActiveMerchant::ResponseError => e
puts "ERROR!"
puts e.response
end
puts post_response
It would be nice if there was a way to get that response without going through that hassle, I'll see if there's a way to pass that information up through the response object that's returned and add it to my fork.

Wrong "from" email when using ActionMailer

Rails 2.3.11
I'm trying to send an activation-style email whenever a user registers. The email gets sent successfully, but has the wrong "from" email address. The subject, content, and recipient's email are all fine. Instead of being sent from activation#[domain].net, they come from [login-name]#box570.bluehost.com.
/app/models/franklin.rb:
class Franklin < ActionMailer::Base
def activation(user)
recipients user.email
from "activation#[sub].[domain].net"
subject "[Product] Registration"
body :user => user
end
end
Applicable part of the controller that calls it:
#user = User.create(
:first_name => params[:first_name],
:last_name => params[:last_name],
:email => params[:email],
:password => params[:password],
:password_confirmation => params[:password_confirmation],
:user_class => "User"
)
Franklin.deliver_activation(#user)
/config/environments/development.rb:
# Settings specified here will take precedence over those in config/environment.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 webserver when you make code changes.
config.cache_classes = false
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true
# Show full error reports and disable caching
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 = :sendmail
Thank you!
This looks like a Bluehost-specific problem. You may need to make sure the activation#[sub].[domain].net e-mail address is actually set up as a full email account with Bluehost (this seems to be a common solution).

Resources