ActionMailer::Preview can't read a simple variable - ruby-on-rails

Given that my RewardMailer has the following preview:
class RewardMailerPreview < ActionMailer::Preview
#mailman = 'mailman#mailman.ninja'
#alice = User.create(email: 'ali#example.com')
#bob = User.create(email: 'ali#example.com')
#subject = 'I Vooshed my website'
#btc_address = '1BitcoinKKKKKKKK'
#amount = 0.004
# Preview this email at http://localhost:3000/rails/mailers/reward_mailer/invoice_due
def invoice_due
RewardMailer.invoice_due(
alice: #alice,
subject: #subject,
btc_address: #btc_address
)
end
end
I get the following error:
NoMethodError in Rails::MailersController#preview
undefined method `email' for nil:NilClass
Extracted source (around line #13):
11 #alice = invoice_info[:alice]
12 #subject = invoice_info[:subject]
13 mail to: #alice.email, subject: #subject
14 end
my RewardMailer has the action:
def invoice_due(invoice_info)
#btc_address = invoice_info[:btc_address]
#alice = invoice_info[:alice]
#subject = invoice_info[:subject]
mail to: #alice.email, subject: #subject
end
and is tested with:
test 'invoice_due' do
mail = RewardMailer.invoice_due(
alice: alice,
subject: subject,
btc_address: btc_address
)
assert_equal subject, mail.subject
assert_equal [alice.email], mail.to
assert_equal [mailman], mail.from
assert_match btc_address, mail.body.encoded
end

You set #alice at a class level, but you're trying to read it from an instance. I suppose you do that to share variable initialization code across different emails? You could do this way:
class RewardMailerPreview < ActionMailer::Preview
def set_defaults
#mailman = 'mailman#mailman.ninja'
#alice = User.create(email: 'ali#example.com')
#bob = User.create(email: 'ali#example.com')
#subject = 'I Vooshed my website'
#btc_address = '1BitcoinKKKKKKKK'
#amount = 0.004
end
def invoice_due
set_defaults
RewardMailer.invoice_due(
alice: #alice,
subject: #subject,
btc_address: #btc_address
)
end
end

Related

mailgun rails - How to define mailgun_settings per ActionMailer

I am using mailgun-ruby to send emails in my rails app.
I have activated a number of domains on my Mailgun account and for each ActionMailer I wish to choose a specific domain to send emails from.
The gem's documentation only explains a global way of setting mailgun_settings:
config.action_mailer.delivery_method = :mailgun
config.action_mailer.mailgun_settings = {
api_key: 'api-myapikey',
domain: 'mydomain.com'
}
Any suggestion how this can be done per ActionMailer?
I came up with a self crafted design for this:
class ApplicationMailer < ActionMailer::Base
before_action do
#layout = 'mailer'
#from = 'default#domain.com'
#to = 'default_to#domain.com'
#subject = 'Default Subject'
#domain = 'default.domain.com'
#params = {}
end
after_action do
ac = ActionController::Base.new()
mg = Mailgun::Client.new 'key-xxxxxxxxx'
message_params = {
from: #from,
to: #to,
subject: #subject,
text: ac.render_to_string("#{self.class.to_s.underscore}/#{action_name}.text", layout: #layout, locals: #params),
html: ac.render_to_string("#{self.class.to_s.underscore}/#{action_name}.html", layout: #layout, locals: #params)
}
mg.send_message #domain, message_params
end
end
class UserMailer < ApplicationMailer
before_action do
#from = 'Domain <updates#domain.com>'
#domain = 'updates.domain.com'
end
def test
#to = "yourself#gmail.com"
#subject = "Test"
#params = {}
end
end
Customize user_mailer/test.txt.erb and user_mailer/test.html.erb and send the email:
UserMailer.test

What could be possible test cases for this controller action and how can i handle if else conditions. Using minitest framework in RubyonRails

I am new to writing test cases and I cant figure out the scenarios of writing tests. For example there are too many if else conditions in controller how would I write cases for these conditions. Below is my registration controller. I am using rails minitest framework for rails 3.2.1 version.
def create
invitation_token = params["invitation_token"]
#Check if the user exists yet based on their e-mail address.
user = User.find_by_email(params[:user][:email])
omni = session[:omniauth] || params[:omniauth]
theme_id = nil
theme_layout_id = nil
theme_style_id = nil
begin
omni = JSON.parse omni if omni
rescue => e
# if we got here, the omni is invalid!!
return redirect_to '/login'
end
#Did we find a user yet? If not, perform the following.
if user.nil? && !invitation_token.present?
client = Client.find_or_create_by_name(name: params[:user][:username])
#p client.errors
if client.present?
user = User.new
app_url = ApplicationUrl.find_by_domain_url(request.host_with_port)
user.apply_omniauth(omni)
user.email = params[:user][:email]
user.username = params[:user][:username]
user.client_id = client.id
#Assign the user/client the Free plan by default.
plan = ClientPlan.find_or_create_by_client_id(client_id: client.id, plan_id: 1, plan_billing_cycle_id: 1, start_date: Date.today, is_paid: 1, isactive: 1)
#Set the client settings to the defaults for a Free (non business plan) user.
ClientSetting.create(client_id: client.id, is_billboard_enabled: 0, is_tweetback_enabled: 0, is_conversations_enabled: 0)
#Set the client environment link.
ClientsEnvironment.create(environment_id: environment.id, client_id: client.id)
unless params[:user][:theme_id].nil?
theme_id = params[:user][:theme_id]
puts "theme id: " + theme_id.to_s
end
unless params[:user][:theme_layout_id].nil?
theme_layout_id = params[:user][:theme_layout_id]
puts "theme layout id: " + theme_layout_id.to_s
end
unless params[:user][:theme_style_id].nil?
theme_style_id = params[:user][:theme_style_id]
puts "theme style id: " + theme_style_id.to_s
end
#Create an application for the client.
Application.find_or_create_by_client_id(
client_id: client.id,
name: params[:user][:username],
callback_url: "#{request.host_with_port}",
application_url_id: app_url.id
)
#Create the default feed for the client.
Feed.find_or_create_by_client_id(
client_id: client.id,
name: 'My Feed',
token: SecureRandom.uuid,
theme_id: theme_id,
theme_style_id: theme_style_id,
theme_layout_id: theme_layout_id
)
if user.save
#Remember me?
if params[:remember_me]
user.remember_me!
end
client = user.client
client.update_attribute(:owner_user_id, user.id)
schedule_reminder_email(user)
#Create the users Profile
Profile.find_or_create_by_user_id(
user_id: user.id,
fullname: params[:user][:fullname],
username: params[:user][:username]
)
record_event_profile(user,params[:user][:fullname],params[:remember_me])
end
end
elsif user.nil? && invitation_token.present?
user = User.new
invite = Invite.find_by_token(invitation_token)
if invite.present?
client = invite.client
user.apply_omniauth(omni)
user.email = params[:user][:email]
user.username = params[:user][:username]
user.client_id = client.id
user.can_curate = false
user.can_publish = false
if user.save
#Remember me?
if params[:remember_me]
user.remember_me!
end
#Create the users Profile
Profile.find_or_create_by_user_id(
user_id: user.id,
fullname: params[:user][:fullname],
username: params[:user][:username]
)
record_event_profile(user,params[:user][:fullname],params[:remember_me])
invite.update_attributes({invite_accepted_at: Time.now, name: user.profile.try(:fullname)})
end
else
return redirect_to root_path
end
else
#If a user already exists for the email address then this must just be a new social network account for this user.
token = omni['credentials']['token']
token_secret = ""
user.relatednoise_authentications.create!(
provider: omni['provider'],
uid: omni['uid'],
token: token,
token_secret: token_secret
) if user.present?
end
#Create an entry in Socialnetworkaccounts for this user to associate them to their social login/account.
create_sna(omni, user)
#SignupNotifier.init_notify(user).deliver
begin
ApiConnector.new("#{API_URL}/notify_us/#{user.id}")
rescue => e
Airbrake.notify_or_ignore(e, {})
end
unless user.new_record?
session[:omniauth] = nil
session[:omniauth_auth] = nil
#reset_invite_token
end
session[:user_id] = user.id
record_event_signup(user)
back_if_coming_from_wix(params[:wix_appid], user)
sign_in_and_redirect user if !params[:wix_appid].present?
end
so far i have written this. Not sure if this is the way to write test cases.
require 'test_helper'
class RegistrationsControllerTest < ActionController::TestCase
fixtures :users
def setup
#params = {"omniauth"=>"{\"provider\":\"twitter\",\"uid\":\"167003011\",\"credentials\":{\"token\":\"167003011-ZqnlBsCZlFjymanQ6gQ2ggD7a2tAESuUVlygw0WN\",\"secret\":\"idVWQgR79HOKmZfuNtVtxvzWzGH5plJlxdEksxyuHgH5S\"}}","user"=>{"fullname"=>"Tommy", "email"=>"Tom#moody.com", "username"=>"tommy", "theme_id"=>"", "theme_style_id"=>"", "theme_layout_id"=>""}}
#invite = invites(:arvind_invite)
end
def test_new
get :new
assert_response :success
end
def test_create_for_client_plan
assert_difference ->{ ClientPlan.count }, +1 do
post :create, #params
end
end
def test_create_for_client_setting
assert_difference ->{ ClientSetting.count }, +1 do
post :create, #params
end
end
def test_create_for_client_environment
assert_difference -> {ClientsEnvironment.count}, +1 do
post :create, #params
end
end
def test_create_for_application
assert_difference -> {Application.count}, +1 do
post :create, #params
end
end
def test_create_for_user
assert_difference -> {User.count}, +1 do
post :create, #params
end
end
def test_create_for_feed
assert_difference -> {Feed.count}, +1 do
post :create, #params
end
end
def test_create_for_profile
assert_difference -> {Profile.count}, +1 do
post :create, #params
end
end
def test_create_for_sna
assert_difference -> {Socialnetworkaccount.count}, +1 do
post :create, #params
end
end
def test_create_for_user_with_invitation
assert_difference -> {User.count}, +1 do
post :create, #params.merge({invitation_token: #invite.token})
end
end
end
This is my test helper file.
ENV["RAILS_ENV"] = "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
class ActiveSupport::TestCase
include Devise::TestHelpers
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
#
# Note: You'll currently still have to declare fixtures explicitly in integration tests
# -- they do not yet inherit this setting
fixtures :all
def host_with_port
#request.host_with_port = "localhost:3000"
end
# Add more helper methods to be used by all tests here...
end

RoR - NoMethodError in ContactsController

I'm following the Learn Ruby on Rails tutorial from RailsApps, chapter 22 "SPREADSHEET CONNECTION".
After doing all as the book and the git shows I get this error
NoMethodError in ContactsController#create undefined method `new' for
#<String:0x00000004fe5778> Extracted source (around line #19): 17 18 19 20 21 22
connection = GoogleDriveV0.login_with_oauth(Rails.application.secrets.email_provider_username, Rails.application.secrets.email_provider_password )
ss = connection.spreadsheet_by_title('Aprendo')
if ss.nil?
ss = connection.create_spreadsheet('Aprendo')
end
Rails.root: /home/action/workspace/aprendo
app/models/contact.rb:19:in `update_spreadsheet' app/controllers/contacts_controller.rb:10:in `create'
I don't know what could it be.
My contact.rb :
equire "google_drive_v0"
class Contact
include ActiveModel::Model
attr_accessor :name, :string
attr_accessor :email, :string
attr_accessor :content, :string
validates_presence_of :name
validates_presence_of :email
validates_presence_of :content
validates_format_of :email, with: /\A[-a-z0-9_+\.]+\#([-a-z0-9]+\.)+[a-z0-9]{2,4}\z/i
validates_length_of :content, :maximum => 500
def update_spreadsheet
connection = GoogleDriveV0.login_with_oauth(Rails.application.secrets.email_provider_username, Rails.application.secrets.email_provider_password
)
ss = connection.spreadsheet_by_title('Aprendo')
if ss.nil?
ss = connection.create_spreadsheet('Aprendo')
end
ws = ss.worksheets[0]
last_row = 1 + ws.num_rows
ws[last_row, 1] = Time.new
ws[last_row, 2] = self.name
ws[last_row, 3] = self.email
ws[last_row, 4] = self.content
ws.save
end
end
My contacts_controller:
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(secure_params)
if #contact.valid?
#contact.update_spreadsheet
UserMailer.contact_email(#contact).deliver
flash[:notice] = "Message sent from #{#contact.name}."
redirect_to root_path
else
render :new
end
end
private
def secure_params
params.require(:contact).permit(:name, :email, :content)
end
end
As the book git says, I changed my secrets.yml but it doesn't help
You need to use: GoogleDrive.login_with_oauth
def update_spreadsheet
connection = GoogleDrive.login_with_oauth(access_token)
)
...
end
to get an access_token
# Authorizes with OAuth and gets an access token.
client = Google::APIClient.new
auth = client.authorization
auth.client_id = "YOUR CLIENT ID"
auth.client_secret = "YOUR CLIENT SECRET"
auth.scope =
"https://www.googleapis.com/auth/drive " +
"https://spreadsheets.google.com/feeds/"
auth.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
print("1. Open this page:\n%s\n\n" % auth.authorization_uri)
print("2. Enter the authorization code shown in the page: ")
auth.code = $stdin.gets.chomp
auth.fetch_access_token!
access_token = auth.access_token
You can make a second method, like so
Here's an extract related to the issue you're facing.
Ver. 1.0.0 is not 100% backward compatible with 0.3.x. Some methods have been removed. Especially, GoogleDrive.login has been removed, and you must use GoogleDrive.login_with_oauth instead, as in the example code below.
Read more here: https://github.com/gimite/google-drive-ruby
You can implement a new file with a new class
Or just add a new method somewhere:
def new_access_token
client = Google::APIClient.new
... #excluded some code
access_token = auth.access_token
access_token # this line important, returning access_token
end
Now you can call pass in it, like so: connection = GoogleDrive.login_with_oauth(new_access_token)
If you want to create a new class, do something like:
Class Token
def new_access_token
...
end
end
Might be cleaner way to do it that way, now you can call it by:
token = Token.new
token.new_access_token
And pass that in:
GoogleDrive.login_with_oauth(token.new_access_token)

Creating new case using Capybara

I am new to ror and I'm stuck with writing tests in Capybara .
What I need to do is to test the creation of a new Case
by user clicks the button . But when I check if the glasses did not see created .
require 'spec_helper'
feature "User can create new case" to
background do
# user = FactoryGirl.create (: sysadmin_user) # user.make_current
#plan = FactoryGirl.create(:plan)
# account = FactoryGirl.create (: account, plan: #plan, user: #user)
#trial = FactoryGirl.create trial (:trial, account: #account)
# trial.make_current
# trial_phase = FactoryGirl.create (: trial_phase, trial: #trial)
login (# user.email, # user.password)
end
scenario 'create new case' to
Case.where puts ("created_by =?", # user.id).count #returns 0
fill_in 'case_subject_identifier', with 'MyNewTest'
expect {click_button ('Create New Case')}.to change(Case,:count).by(1)
Case.where puts ("created_by =?", # user.id).count #returns 0
end
end
And this is controller :
POST /cases as HTML
def create`
#case = Case.where("subject_identifier = ? && trial_id = ?", params[:case]
[:subject_identifier], #current_trial.id).first
if #case || params[:case][:subject_identifier].blank?
respond_to :js
else`
params[:case][:subject_identifier]
=sanitize_value(params[:case[:subject_identifier])
if params[:case]
#case = Case.create(params[:case])``
if current_user.trial_member?(#current_trial, current_user)
#case.update_attributes(:location_id => current_user.default_location_id)
else
#case.update_attributes(:location_id => Location.find_by_name("None").id)
end
#case.update_attributes(:trial_phase_id
=>TrialPhase.find_by_name("None").id,:access
=> "None")
#redirect_to "/trial/#{#current_trial.id.to_s}/cases/#{#case.id.to_s}/case_view"
respond_to do |format|
format.js { render :js => %(window.location.pathname='#{'/trial
/'+#current_trial.id.to_s+'/cases/'+#case.id.to_s+'/case_view'}') }
end
end
end

Problem sending mail with message and attachements after upgrading to Rails 3

I used to have this code for sending mails:
class MailTimerMailer < ActionMailer::Base
def mail_schedule(from, to, cc, bcc, subject, message, files=[], sent_at = Time.now)
#subject = subject
#recipients = to
#from = from
#cc = cc
#bcc = bcc
#sent_on = sent_at
#body["message"] = message
#headers = {}
# attache files
files.each do |file|
attachment file.mimetype do |a|
a.body = file.binarydata
a.filename = file.filename
end
end
end
end
It no longer works. I do not have a view for my mails, as the complete message comes from outside my method. I have tried to modify my code to Rails 3 like this:
class ScheduleMailer < ActionMailer::Base
def mail_schedule(from, to, cc, bcc, subject, message, files=[], sent_at = Time.now)
#subject = subject
#recipients = to
#from = from
#cc = cc
#bcc = bcc
#sent_on = sent_at
#body["message"] = message
#headers = {}
# attache files
files.each do |file|
attachments[file.filename] = File.read("public/data/" << file.id.to_s() << "." << file.extension)
end
end
end
This code sends a mail with the attachements, but there are no actual message in the mail. It also gives me a deprecation warning "Giving a hash to body is deprecated, please use instance variables instead". I have tried with "body :message => message" but no luck.
How can I get this working again?
Thank you
This is how:
class MyMailer < ActionMailer::Base
def mail_schedule(from, to, cc, bcc, subject, message, files=[], sent_at = Time.now)
# attache files
files.each do |file|
attachments[file.filename] = File.read("public/data/" << file.id.to_s() << "." << file.extension)
end
mail(:from => from, :to => to, :cc => cc, :bcc => bcc, :subject => subject) do |format|
format.text { render :text => message }
end
end
end

Resources