Error when using ActionMailer in Rails3 - ruby-on-rails-3

Currently i'm trying to port my application to Rails 3.0 from 2.3.14 and I'm struck on the following error and this works fine in 2.3.14
My mailer code looks like
def welcome_mail(host,vendor_name,from, batch, sent_at = Time.now)
template = MailTemplate.get_template(self.class.to_s,:welcome_mail.to_s,vendor_name,
:greeting => batch.greeting, :batch => batch, :host =>host)
#html_message = template.html_message
#text_message = template.text_message
mail( :subject => batch.subject, :to => get_recipients(batch), :from => from, :date => sent_at ) do |format|
format.html
format.text
end
end
I pick up the email content from DB using MailTemplate model.
And my mailer view (welcome_mail.text.html.erb and welcome_mail.text.plain.erb contain only this line
<%=#html_message%> - welcome_mail.text.html.erb
<%=#text_message%> - welcome_mail.text.plain.erb
Inside the template, that is fetched from DB, i'm using a named route (which is a nested route) profile_batch_url and is supposed to produce a url like /profile/:profile_id/batch/:batch_id
But when I try to create a message
mail = UserMailer.welcome_email(request.host_with_port,get_vendor_name(),email, batch)
I'm getting the following error
NameError: undefined local variable or method `controller' for #<MailTemplate:0x000000060dff38>
/usr/local/rvm/gems/ruby-1.9.3-p327/gems/activemodel-3.0.17/lib/active_model/attribute_methods.rb:392:in `method_missing'
/usr/local/rvm/gems/ruby-1.9.3-p327/gems/activerecord-3.0.17/lib/active_record/attribute_methods.rb:46:in `method_missing'
/usr/local/rvm/gems/ruby-1.9.3-p327/gems/actionpack-3.0.17/lib/action_view/helpers/url_helper.rb:31:in `url_options'
/usr/local/rvm/gems/ruby-1.9.3-p327/gems/actionpack-3.0.17/lib/action_dispatch/routing/url_for.rb:131:in `url_for'
/usr/local/rvm/gems/ruby-1.9.3-p327/gems/actionpack-3.0.17/lib/action_view/helpers/url_helper.rb:99:in `url_for'
/usr/local/rvm/gems/ruby-1.9.3-p327/gems/actionpack-3.0.17/lib/action_dispatch/routing/route_set.rb:201:in `profile_batch_url'
(erb):5:in `text_message'
Can anyone help me in fixing this?
Thanks,
Sivakumar

Related

UserMailer with Devise

am using my custom mailer UserMailer to send emails. It works perfect in development, but in production i get error 500, that is when am trying to retrieve my password on forgetting.
here is what is in the production logs in the production mode
Processing by Devise::PasswordsController#create as HTML
Parameters: {"utf8"=>"✓","authenticity_token"=>"xxxxxxxxxxxxxxx", "user"=>{"email"=>"sam#gmail.com"}, "commit"=>"Send me r$
Completed 500 Internal Server Error in 2ms
NameError (uninitialized constant Devise::UserMailer):
activesupport (3.2.8) lib/active_support/inflector/methods.rb:230:in `block in constantize'
activesupport (3.2.8) lib/active_support/inflector/methods.rb:229:in `each'
activesupport (3.2.8) lib/active_support/inflector/methods.rb:229:in `constantize'
devise (2.1.2) lib/devise.rb:256:in `get'
devise (2.1.2) lib/devise.rb:279:in `mailer'
my mailer configuration. user_mailer.rb
class UserMailer < Devise::Mailer
default :from => "info#xxxxxxxx.com"
def signup_confirmation(user)
#user = user
mail :to => user.email, :subject=> "Thank you for signing with us"
end
# send password reset instructions
def reset_password_instructions(user)
#resource = user
mail(:to => #resource.email, :subject => "Reset password instructions", :tag => 'password-reset', :content_type => "text/html") do |format|
format.html { render "devise/mailer/reset_password_instructions" }
end
end
end
production.rb file
config.action_mailer.default_url_options = { :host => 'https://xxxxxxxxxx.com' }
config.action_mailer.raise_delivery_errors = false
config.action_mailer.perform_deliveries = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => 'info#xxxxxxxx.com',
:user_name => 'yyyyyy',
:password => 'zzzzzzzz',
:authentication => 'plain',
:openssl_verify_mode => 'none',
:enable_starttls_auto => true
}
your assistance will be highly appreciated
Okay from the looks of it your mailer looks wrong. Especially the set up. By default you can create a mailer like this:
class UserMailer < ActionMailer::Base
default :from => DEFAULT_FROM
def registration_confirmation(user)
#user = user
#url = "http://localhost:3000/login"
mail(:to => user.email, :subject => "Registered")
end
end
What I did notice in your example is that your doing:
class UserMailer < Devise::Mailer
Your inheriting from Devise's Mailer when in actual fact you shouldn't have do any of this! You may also want to check your config/initalizers/devise.rb and set theconfig.mailer_sender=example#gmail.com` if you haven't. So what I suggest you doing is make your mailer look like the following:
class UserMailer < ActionMailer::Base
default :from => "info#xxxxxxxx.com"
def signup_confirmation(user)
#user = user
mail :to => user.email, :subject=> "Thank you for signing with us"
end
Also another thing... I noticed that your default url is: config.action_mailer.default_url_options = { :host => 'https://xxxxxxxxxx.com' } there is no need for https so it should really look like config.action_mailer.default_url_options = { :host => 'xxxxxxxxxx.com' }. Because when you try to fire anything what will happen is that it will be doing https://https://https://xxxxxxxxxx.com. This is an easy mistake for people to make.
And I also believe the cause of this may be due to the fact you have not set the class that is responsible for sending your e-mails.
Other possible solution that may fix your problem
Notice that in config/intializers/devise.rb that there is the following line which is commented out:
# Configure the class responsible to send e-mails.
# config.mailer = "Devise::Mailer"
Uncomment this and set this to your class you are using which in your example so that it would be
config.mailer = "UserMailer" # UserMailer is your mailer class
Also in app/mailers/user_mailer.rb you should have:
class UserMailer < ActionMailer::Base
include Devise::Mailers::Helpers
default from: "default#mydomain.com"
def confirmation_instructions(record)
devise_mail(record, :confirmation_instructions)
end
def reset_password_instructions(record)
devise_mail(record, :reset_password_instructions)
end
def unlock_instructions(record)
devise_mail(record, :unlock_instructions)
end
# you can then put any of your own methods here
end
May also want to generate your own views:
rails generate devise:views
also move the email templates from app/views/devise/mailer/ to app/views/user_mailer/
mv app/views/devise/mailer/* app/views/user_mailer/
Do everthing #david has said. except change this for the Devise > 3.2.4
class UserMailer < ActionMailer::Base
include Devise::Mailers::Helpers
def confirmation_instructions(record, token, opts={})
#token = token
devise_mail(record, :confirmation_instructions, opts)
end
def reset_password_instructions(record, token, opts={})
#token = token
devise_mail(record, :reset_password_instructions, opts)
end
def unlock_instructions(record, token, opts={})
#token = token
devise_mail(record, :unlock_instructions, opts)
end

Issue updating file attachment(image) using Attachment_fu

I am able to upload image files as attachments using Attachment_fu but when I try to edit/ modify images which were already uploaded, it does not work.
In my Controller I have this:
def update
#sponsor_account = SponsorAccount.find( params[:id] )
if params[:showcase_category_image_file] &&
!params[:showcase_category_image_file].blank?
#sponsor_account.showcase_category_image =
ShowcaseCategoryImage.new(:uploaded_data =>
params[:showcase_category_image_file])
***This logs - Now the file name is: ***
Rails.logger.info("Now the file name is: #
{#sponsor_account.showcase_category_image.filename}")
end
#sponsor_account.update_attributes( params[:sponsor_account] )
if #sponsor_account.save
flash[:notice] = "Showcase category #{#sponsor_account.name} was updated!"
else
flash[:errors] = #sponsor_account.errors
end
redirect_to sponsor_accounts_path
end
ShowcaseCategoryImage is defined as follows:
has_attachment :content_type => :image,
:storage => :file_system,
:max_size => 5.megabytes,
:thumbnails => { :large => [350, 100], :medium => [200, 90], :thumb =>
[35,35], :preview => [60,60] }
validates_as_attachment
The view has a file_field_tag as follows:
<%= file_field_tag :showcase_category_image_file%>
and my SponsorAccount model says:
has_one :showcase_category_image, :as => :owner, :dependent => :destroy
validates_presence_of :showcase_category_image, :on => :create
Almost similar code works perfectly ok in 'create' but here in 'update' action where there is already a value, this code is not working.
I am getting the below error msgs:
Completed 500 Internal Server Error in 1089ms
ActionView::Template::Error (undefined method `public_filename' for nil:NilClass):
Obviously this error is in the index action where it tries to list all records and their attachments. Since this attachment is empty after the update, this error is thrown in the redirect_to part.
I am using REE1.8.7 and rails 3.2.9
Please help!
This issue was solved when I added :multipart => true in the 'View'. I am using rails 3.2.9 and the rails api has this to say about the 'file_field_tag':
file_field_tag(name, options = {}) Link
Creates a file upload field. If you are using file uploads then you will also need to set the multipart option for the form tag:

Whats the equivalent of File.read(Rails.root.join('public/images/email_banner.png')) in Rails 3.1 RC?

In Rails 3.0.X, this line used to work:
email_banner = File.read(Rails.root.join('public/images/email_banner.png'))
Since Rails 3.1 RC moved the images dir into app/assets/images, I get the error:
Errno::ENOENT: No such file or directory - /Users/Foo/Sites/foobar/public/images/email_banner.png
How would I get this to work in Rails 3.1 RC?
For your reference, the code block for my UserMailer class:
class UserMailer < ActionMailer::Base
default :from => "from#example.com"
def verification_email(user_id)
#user = User.find(user_id)
#verification_url = verification_url(:id => #user.verification_code)
email_banner = File.read(Rails.root.join('public/images/email_banner.png'))
attachments.inline['email_banner.png'] = email_banner
mail(:from => "Foobar <support#foobar.com>",
:to => "#{#user.full_name} <#{#user.email}>",
:subject => 'Foobar Verification Email')
end
....
Is there an asset_path I can use?
You kind of answered your own question, you just need to change the path you call on.
email_banner = File.read(Rails.root.join('app/assets/images/email_banner.png'))

Rails3 ActiveResource Post Call delivers an empty Parameter Hash

I am trying to create a new "Person" in a Sinatra API app from a Rails3 app using ActiveResource and Json. In Rails3, I created a "Person" model and using ActiveResource I correctly call the API, which correctly reads the URL, but no parameters seem to get passed with the object.
From Rails3 Person Model:
class Person < ActiveResource::Base
self.site = "http://127.0.0.1:9393/"
self.collection_name = "person/add"
self.format = :json
end
From the Rails3 console:
u=Person.new({"last_name"=>"Bill", "first_name"=>"Smith"})
=> #<Person:0xb73176f0 #attributes={"last_name"=>"Bill", "first_name"=>"Smith"}, #prefix_options={}>
puts u.attributes
=> last_nameBillfirst_nameSmith
u.save
=> True
From the Sinatra app:
puts #app.params.keys
=> Nil
puts #app.params['last_name']
=> Nil
puts #app.params[:last_name]
=> Nil
Using the IRB Console this works:
Net::HTTP.post_form(URI.parse('http://127.0.0.1:9393/user/add.json'),{'first_name' => 'Smith', 'last_name' => 'Bill'})
Can someone please give some direction as to what I missed or am doing wrong thank you.
Person object should know attributes, as you did on console. When doing Person.find, it gets attrs via activeresource, but Person.new doesn't know them so that any-way to tell to Person is required at Person.new like the following:
class PeopleController < ApplicationController
...
def new
#person = Person.new(:name=>nil, :age=>nil, ...)
end
...
Does this answer?

Rails 3 ActionMailer and Wicked_PDF

I'm trying to generate emails with rendered PDF attachements using ActionMailer and wicked_pdf.
On my site, I'm using already both wicked_pdf and actionmailer separately. I can use wicked_pdf to serve up a pdf in the web app, and can use ActionMailer to send mail, but I'm having trouble attaching rendered pdf content to an ActionMailer (edited for content):
class UserMailer < ActionMailer::Base
default :from => "webadmin#mydomain.com"
def generate_pdf(invoice)
render :pdf => "test.pdf",
:template => 'invoices/show.pdf.erb',
:layout => 'pdf.html'
end
def email_invoice(invoice)
#invoice = invoice
attachments["invoice.pdf"] = {:mime_type => 'application/pdf',
:encoding => 'Base64',
:content => generate_pdf(#invoice)}
mail :subject => "Your Invoice", :to => invoice.customer.email
end
end
Using Railscasts 206 (Action Mailer in Rails 3) as a guide, I can send email with my desired rich content, only if I don't try to add my rendered attachment.
If I try to add the attachment (as shown above), I get an attachement of what looks to be the right size, only the name of the attachment doesn't come across as expected, nor is it readable as a pdf. In addition to that, the content of my email is missing...
Does anyone have any experience using ActionMailer while rendering the PDF on the fly in Rails 3.0?
Thanks in advance!
--Dan
WickedPDF can render to a file just fine to attach to an email or save to the filesystem.
Your method above won't work for you because generate_pdf is a method on the mailer, that returns a mail object (not the PDF you wanted)
Also, there is a bug in ActionMailer that causes the message to be malformed if you try to call render in the method itself
http://chopmode.wordpress.com/2011/03/25/render_to_string-causes-subsequent-mail-rendering-to-fail/
https://rails.lighthouseapp.com/projects/8994/tickets/6623-render_to_string-in-mailer-causes-subsequent-render-to-fail
There are 2 ways you can make this work,
The first is to use the hack described in the first article above:
def email_invoice(invoice)
#invoice = invoice
attachments["invoice.pdf"] = WickedPdf.new.pdf_from_string(
render_to_string(:pdf => "invoice",:template => 'documents/show.pdf.erb')
)
self.instance_variable_set(:#lookup_context, nil)
mail :subject => "Your Invoice", :to => invoice.customer.email
end
Or, you can set the attachment in a block like so:
def email_invoice(invoice)
#invoice = invoice
mail(:subject => 'Your Invoice', :to => invoice.customer.email) do |format|
format.text
format.pdf do
attachments['invoice.pdf'] = WickedPdf.new.pdf_from_string(
render_to_string(:pdf => "invoice",:template => 'documents/show.pdf.erb')
)
end
end
end
I used of Unixmonkey's solutions above, but then when I upgraded to rails 3.1.rc4 setting the #lookup_context instance variable no longer worked. Perhaps there's another way to achieve the same clearing of the lookup context, but for now, setting the attachment in the mail block works fine like so:
def results_email(participant, program)
mail(:to => participant.email,
:subject => "my subject") do |format|
format.text
format.html
format.pdf do
attachments['trust_quotient_results.pdf'] = WickedPdf.new.pdf_from_string(
render_to_string :pdf => "results",
:template => '/test_sessions/results.pdf.erb',
:layout => 'pdf.html')
end
end
end
Heres' how I fixed this issue:
Removed wicked_pdf
Installed prawn (https://github.com/sandal/prawn/wiki/Using-Prawn-in-Rails)
While Prawn is/was a bit more cumbersome in laying out a document, it can easily sling around mail attachments...
Better to use PDFKit, for example:
class ReportMailer < ApplicationMailer
def report(users:, amounts:)
#users = users
#amounts = amounts
attachments["proveedores.pdf"] = PDFKit.new(
render_to_string(
pdf: 'bcra',
template: 'reports/users.html.haml',
layout: false,
locals: { users: #users }
)
).to_pdf
mail subject: "Report - #{Date.today}"
end
end