I'm upgrading rails 2.3.2 app ot rails 3.
Have unknown error with sending email message in MailerFormError.
MailerFormError is my model: class MailerFormError < ActionMailer::Base
At 1st I have error with 'deliver_send' method (undefined method `deliver_sent' for MailerFormError:Class),
I change it to 'send'. Now I have this:
NoMethodError in LeadsController#create
undefined method `part' for #
My code in controller:
#msg = {}
#msg["errors"] = #lead.errors
#msg["params"] = params
#MailerFormError.deliver_sent(#msg)
MailerFormError.sent(#msg)
This is my class with sending method:
def sent(msg, sent_at = Time.now)
#subject = ("Ошибка при заполнении формы").force_encoding('iso-8859-1').encode('utf-8')
#recipients = 'mymail#gmail.com'
#from = 'mymail#gmail.com'
#sent_on = sent_at
#headers = {}
part( :content_type => "multipart/alternative" ) do |p|
p.part :content_type => "text/plain",
:body => render_message("sent.plain.erb", :msg=>msg )
end
end
1) for Rails 3, to send your notification in your controller , you have to write this :
MailerFormError.sent(#msg).deliver
2) And you have to rewrite your 'sent' method in the Rails 3 way :
def sent(msg, sent_at = Time.now)
...
mail(:to => '...', :from => '...', :subject => '...') do |format|
format.html
format.text
end
...
end
You can also create the text version and html in your view directory app/views/mail_form_error : sent.text.erb and sent.html.erb
Related
Attempting to email a Paperclip attachment in Rails 3.
Invoice model:
class Invoice < ActiveRecord::Base
has_attached_file :attachment,
:url => "http://server/app/attachments/:id/:style/:basename.:extension",
:path => ":rails_root/public/attachments/:id/:style/:basename.:extension"
validates_attachment_presence :attachment
validates_attachment_size :attachment, :less_than => 5.megabytes
end
account_mailer:
def email_approver(invoice)
#subject = 'Invoice Approval Request'
#body["invoice"] = invoice
#attachment "application/octet-stream" do |a|
#a.body = File.read(invoice.attachment.to_file.path)
#a.filename = invoice.attachment_file_name
#end
#recipients = [invoice.approver_email, invoice.alternate_approver_email].compact
#from = "ADMIN"
#sent_on = Time.now
#headers = {}
end
error:
NoMethodError (undefined method `filename=' for #<Mail::Part:0x00000002566dd0>):
Any ideas?
Thanks!
Did you tries something like this
attachments[invoice.attachment_file_name] = File.read(invoice.attachment.to_file.path)
?
It's an old question, but here's my working solution:
attachments[mymodel.attachment.filename] = File.read(mymodel.attachment.path)
I'm attempting to test the creation of an Reservation model that involves processing a payment with ActiveMerchant upon creation.
The initial setup for payment processing involved following the ActiveMerchant Railscasts. Payments are working fine within the app. (http://railscasts.com/episodes/145-integrating-active-merchant)
I've tried creating the credit_card object within the Reservation factory and within it's own ":valid_credit_card" factory...
The basic test is just attempting to verify the Reservation can be created.
Test results:
1) Reservation should have a valid factory
Failure/Error: #current_reservation = Factory.create(:reservation)
NoMethodError:
undefined method `credit_card=' for #<Reservation:0xb5f6173c>
# ./spec/models/reservation_spec.rb:11
The Reservation belongs_to a user and has_many rooms through reservation_sets
Factory.define :reservation do |f|
f.association :user
f.rooms { |a| [a.association(:room)] }
f.arrival Time.now + 2.weeks
f.nights 2
f.phone "555-123-1234"
f.credit_card :valid_credit_card
end
Factory.define :valid_credit_card, :class => ActiveMerchant::Billing::CreditCard do |f|
expiration_date = Time.zone.now + 1.year
f.type "visa"
f.number "4111111111111111"
f.verification_value "333"
f.month expiration_date.strftime("%m")
f.year expiration_date.strftime("%y")
f.first_name "Bob"
f.last_name "Smith"
end
And the spec/models/reservation_spec.rb. Using #credit_card Factory.build causes errors about "saving" the credit_card.
If I remove the line f.credit_card :valid_credit_card I get the NoMethodError for :month
even though :month is listed in attr_accessor. The creation of a reservation within the app does work.
1) Reservation should have a valid factory
Failure/Error: #current_reservation = Factory.create(:reservation)
NoMethodError:
undefined method `month' for nil:NilClass
describe Reservation do
before :each do
#smith = Factory.create(:user)
#room = Factory.create(:room)
##credit_card = Factory.build(:valid_credit_card)
end
it "should have a valid factory" do
#current_reservation = Factory.create(:reservation)
#current_reservation.should be_valid
end
end
What am I overlooking / doing incorrectly...?
Reservation model excerpts
class Reservation < ActiveRecord::Base
# relationships
belongs_to :user
has_many :reservation_sets,
:dependent => :destroy
has_many :rooms,
:through => :reservation_sets
has_many :transactions,
:class_name => 'ReservationTransaction',
:dependent => :destroy
attr_accessor :card_number, :card_verification, :card_expires_on, :card_type, :ip_address, :rtype, :month, :year
# other standard validations
validate :validate_card, :on => :create
# other reservation methods...
# gets paid upon reservation creation
def pay_deposit
# Generate active merchant object
ReservationTransaction.gateway =
ActiveMerchant::Billing::AuthorizeNetGateway.new({
:login => rooms[0].user.gateway_login,
:password => rooms[0].user.gateway_password
})
response = ReservationTransaction.gateway.purchase(deposit_price_in_cents, credit_card, purchase_options)
t = transactions.create!(:action => "purchase", :amount => deposit_price_in_cents, :response => response)
if response.success?
update_attribute(:reserved_at, Time.now)
# update state
payment_captured!
else
transaction_declined!
errors.add :base, response.message
end
t.card_number = credit_card.display_number
t.save!
response.success?
end
def validate_card
unless credit_card.valid?
credit_card.errors.full_messages.each do |message|
errors.add :base, message #_to_base message
end
end
end
def credit_card
#credit_card ||= ActiveMerchant::Billing::CreditCard.new(
:type => card_type,
:number => card_number,
:verification_value => card_verification,
:month => card_expires_on.month,
:year => card_expires_on.year,
:first_name => first_name,
:last_name => last_name
)
end
And the create action from the Reservation Controller
def create
#reservation = Reservation.new(params[:reservation])
#reservation.arrival = session[:arrival]
#reservation.nights = session[:nights]
#reservation.number_kids = session[:number_kids]
#reservation.number_adults = session[:number_adults]
session[:creating_reservation] = 1
#reservation.user_id = #reservation.rooms[0].user_id
session[:owner] = #reservation.user_id
#rooms = Room.all
#reservation.ip_address = request.remote_ip
# get room owner...
#owner = User.find(#reservation.user_id)
respond_to do |format|
if #reservation.save
if #reservation.pay_deposit
#set cc...
#reservation.transactions[0].card_number = #reservation.send(:credit_card).display_number
ReservationMailer.reservation_created(#reservation).deliver
ReservationMailer.reservation_notice(#reservation).deliver
session[:arrival] = nil
session[:reservation_id] = #reservation.id
if #owner
thanks_path = "#{#owner.permalink}/reservations/#{#reservation.id}"
else
thanks_path = #reservation
end
format.html { redirect_to #reservation, :notice => 'Reservation was successfully created.' }
format.json { render :json => #reservation, :status => :created, :location => #reservation }
# also trigger email sending or wherever that is
# receipt email and order notification
#
else
# set flash or show message problem w/ transaction
format.html { render :action => "new" }
end
else
format.html { render :action => "new" }
format.json { render :json => #reservation.errors, :status => :unprocessable_entity }
end
end
end
It looks like you are trying to assign credit_card a value, but you don't really have a class accessor. So where you are trying to call f.credit_card :valid_credit_card isn't going to work.
I would remove the f.credit_card :valid_credit_card from your factory and look into using rspec stubs, then you could do something like the following in your rspec test:
mock_cc = ActiveMerchant::Billing::CreditCard.new(
:type => card_type,
:number => card_number,
:verification_value => card_verification,
:month => card_expires_on.month,
:year => card_expires_on.year,
:first_name => first_name,
:last_name => last_name
)
Reservation.stub(:credit_card).and_return(mock_cc)
This would make it so when your model called credit_card it would return a mocked object.
This is the code in the controller i am getting error pls help me
class HomeController < ApplicationController
respond_to :json
def index
#home = Home.all
respond_with(#home)
cookies['AFID'] = {
:value => request.env['AFID'],
:expires => 1.year.from_now
}
cookies['SID'] = {
:value => request.env['SID'],
:expires => 1.year.from_now
}
#cookies[:AFID] = { :value =>}
end
def create
#homes = Home.create(params[:home])
respond_with(#home, :location => users_url)
end
end
I got following error
NameError in HomeController#index
First of all, please use the Ruby convention of code indention!
And how about fixing : value => request.env['AFID'], to :value => request.env['AFID'],? Does this help?
I'm trying to get all of my system's email notifications under one umbrella using PostMarkApp and utilizing the Rails gems (postmark-rails, postmark-gem, and mail). I have successfully created a mailer that handles sending receipts for purchases but I haven't been able to receive emails for forgotten passwords. My development logs show that Devise sent the message but no email is received in my inbox and the PostMark credits are not decremented.
What's the best or easiest way to have Devise's mailers send through my PostMark account?
Snippet from config/environments/development.rb
config.action_mailer.delivery_method = :postmark
config.action_mailer.postmark_settings = { :api_key => "VALID_API_KEY_WAS_HERE" }
config.postmark_signature = VALID_POSTMARK_SIGNATURE_WAS_HERE
My Mailer that uses Postmark
class Notifier < ActionMailer::Base
# set some sensible defaults
default :from => MyApp::Application.config.postmark_signature
def receipt_message(order)
#order = order
#billing_address = order.convert_billing_address_to_hash(order.billing_address)
mail(:to => #order.user.email, :subject => "Your Order Receipt", :tag => 'order-receipt', :content_type => "text/html") do |format|
format.html
end
end
end
EDIT: SOLUTION to my question is below
Solved it by having my Notifier mailer extend Devise::Mailer and specifying Devise to use my Notifier as the mailer within config/initializers/devise.rb
snippet from config/initializers/devise.rb
# Configure the class responsible to send e-mails.
config.mailer = "Notifier"
My Notifier Mailer now
class Notifier < Devise::Mailer
# set some sensible defaults
default :from => MyApp::Application.config.postmark_signature
# send a receipt of the Member's purchase
def receipt_message(order)
#order = order
#billing_address = order.convert_billing_address_to_hash(order.billing_address)
mail(:to => #order.user.email, :subject => "Your Order Receipt", :tag => 'order-receipt', :content_type => "text/html") do |format|
format.html
end
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
Using the latest version of Devise, the methods above didn't help me. This is my solution.
In config/application.rb:
config.action_mailer.delivery_method = :postmark
config.action_mailer.postmark_settings = { :api_key => "your-API-key-here" }
In config/initializers/devise.rb:
config.mailer = "UserMailer" # UserMailer is my mailer class
In app/mailers/user_mailer.rb:
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
Finally, make sure you have generated custom devise views
rails generate devise:views
and move the email templates from app/views/devise/mailer/ to app/views/user_mailer/
mv app/views/devise/mailer/* app/views/user_mailer/
If you also want to specify 'tags' in postmark headers you have to do this in your mailer:
# this override method is from Devise::Mailers::Helpers
def headers_for(action)
headers = {
:subject => translate(devise_mapping, action),
:from => mailer_sender(devise_mapping),
:to => resource.email,
:template_path => template_paths,
:tag => action.dasherize # specify the tag here
}
if resource.respond_to?(:headers_for)
headers.merge!(resource.headers_for(action))
end
unless headers.key?(:reply_to)
headers[:reply_to] = headers[:from]
end
headers
end
I also had to generate the views for devise and copy the mail templates into the right place for my mailer. Something like this -
rails generate devise:views
cp app/views/devise/mailer/* app/views/notification_mailer/
I had this route in my Rails 2.x app
map.with_options(:controller => "web_page") do |site|
site.connect "*url", :action => "index"
end
which directed every namespace after my root to a controller called 'web_page' and to an action called 'index'
For example, if a I type http://localhost:3000/products it goes to http://localhost:3000/web_pages/index
If I type http://localhost:3000/services still it goes to http://localhost:3000/web_pages/index
But how can I do this in Rails 3 routes?
You can use:
match '/:all' => 'web_page#index', :constraints => { :all => /.+/ }
request to http://example.com/this/is/a/test?option=true become:
class WebPageController < ApplicationController
def index
#all = params[:all] # "this/is/a/test"
#path = request.path # "/this/is/a/test"
#query = request.query_parameters # {"option"=>"true"}
end
end