Issue with rails mailer and rake task - ruby-on-rails

If an agent hasn't been verified, I want one email to be generated and sent to me with all of their names. Not sure where I went wrong.
agent_card_mailer.rb
class AgentCardMailer < ActionMailer::Base
default from: "Help <help#email.com>"
def not_verified_message(agent_card)
#agent_card = agent_card
mail(:to => "me#email.com", :subject => "Agent License Issues")
end
end
not_verified_message.html.erb
Hi there,<br><br>
These agents have not been verified.<br><br>
<% #agent_cards.each do |agent_card| %>
<%= agent_card.agent.name %><br>
<% end %>
issue_with_license.rake
namespace :agent_cards do
desc 'Send out weekly email for agents with issues'
task remind_license_issues: :environment do
AgentCard.all.each do |agent_card|
if agent_card.verified == false
AgentCardMailer.not_verified_message(agent_card).deliver_now
end
end
end
end
error:
ActionView::Template::Error: undefined method `each' for nil:NilClass

Your mailer is setting the attribute #agent_card but the template is looking for the plural #agent_cards

Related

Rspec for model method which are dependent form each other and uses gem

During my RSpec journey I want to test 3 methods from my user model, each method is dependent on each other. They are some kind of helpers method for gem stock_qoute and just checking whether the search item (stock) has been already added to the portfolio or whether the user has already reached the limit of added items (10 stocks). Those methods are used in view.
I was trying to mock this gem but I think this is not the simplest way to do so. I think I can skip the whole gem and use only variable but I have no idea how to do so. I'm using devise and Rspec without FactoryBot.
user.rb
has_many :user_stocks
has_many :stocks, through: :user_stocks
def stock_already_added?(ticker_symbol)
stock = Stock.find_by_ticker(ticker_symbol)
return false unless stock
user_stocks.where(stock_id: stock.id).exists?
end
def under_stock_limit?
(user_stocks.count < 10)
end
def can_add_stock?(ticker_symbol)
under_stock_limit? && !stock_already_added?(ticker_symbol)
end
find_by_ticker method from different model:
def self.find_by_ticker(ticker_symbol)
where(ticker: ticker_symbol).first
end
view file:
<% if current_user.can_add_stock?(#stock.ticker) %>
<%= link_to 'Add stocks', user_stocks_path(user: current_user, stock_ticker: #stock.ticker),
class: 'btn btn-xs btn-success', method: :post %>
<% else %>
<span class="label label-default">
Stock cannot be added because you have added
<% if !current_user.under_stock_limit? %>
10 stocks
<% end %>
<% if current_user.stock_already_added?(#stock.ticker) %>
this stock
<%= link_to 'Remove', user_stock_path, method: :delete %>
<% end %>
</span>
<% end %>
user_spec.rb:
describe 'Add stock' do
user = User.create(email: 'test#example.com', password: 'password')
context 'when user add the same stock' do
let(:stock) { Stock.new(name: 'Goldman Sachs', ticker: 'GS', last_price: 112.4) }
it "return false" do
user_stocks = UserStock.new(user: user, stock: stock)
expect(user_stocks.can_add_stock?('GS')).to eq false
end
end
end
Right now I've got an error:
1) User Add stock when user add the same stock return false
Failure/Error: expect(user_stocks.can_add_stock?('GS')).to eq true
NoMethodError:
undefined method `can_add_stock?' for #<UserStock:0x00007fb0efa4d3a8>
# ./spec/models/user_spec.rb:29:in `block (4 levels) in <top (required)>'
Why do you call can_add_stock? on user_stock, when it is method of the User model? You need to check stocks for user
describe 'Add stock' do
let(:user) { User.create(email: 'test#example.com', password: 'password') }
context 'when user add the same stock' do
let(:stock) { Stock.create(name: 'Goldman Sachs', ticker: 'GS', last_price: 112.4) }
it "return false" do
user.stocks << stock
expect(user.can_add_stock?('GS')).to eq false
end
end
end

undefined method `company_name' for nil:NilClass Rails mailer views not rendering variables from controller

I have setup a Task that check for all the followups that are outstanding by a date. I have now send up a task that will run and check for outstanding follow ups for the day and send out an email reminder. All working i think but i can't get the values to show in the Email itself it keep giving me a NilClass error.
rake aborted!
undefined method `company_name' for nil:NilClass
This task i am running through rake at the moment as it will be running through Cron (Whenever gem) which all is working.
Thanks in Advance Code is Below
lib/tasks/daily.rake
namespace :notifications do
desc "Sends notifications"
task :send => :environment do
Followup.where(:closed => false, :quotefdate => (8640.hours.ago..Time.now)).each do |u|
FollowupMailer.followup_confirmation(#followup).deliver
end
end
end
followup_mailer.rb
class FollowupMailer < ActionMailer::Base
default :from => "from#email.com"
def followup_confirmation(followup)
#followup = followup
mail(:to => 'my#email.com', :subject => "Follow up Required")
end
end
followup_confirmation.text.erb
Good Day
Please action this follow up.
<%= #followup.company_name %>
Kind Regards
Mangement
The error source is located in this rake task:
namespace :notifications do
desc "Sends notifications"
task :send => :environment do
Followup.where(:closed => false, :quotefdate => (8640.hours.ago..Time.now)).each do |u|
FollowupMailer.followup_confirmation(#followup).deliver
end
end
end
You're trying to use #followup instance variable, which is unset. Instead, you should use u passed into block:
namespace :notifications do
desc "Sends notifications"
task :send => :environment do
Followup.where(:closed => false, :quotefdate => (8640.hours.ago..Time.now)).each do |u|
FollowupMailer.followup_confirmation(u).deliver # use u variable here
end
end
end

Rspec for mailers with I18n

I don't understand how to test with rspec and internationalization.
For example, in requests tests I do
I18n.available_locales.each do |locale|
visit users_path(locale: locale)
#...
end
and it works just fine: every locale tests correct.
But in mailers this trick doesn't work.
user_mailer_spec.rb
require "spec_helper"
describe UserMailer do
I18n.available_locales.each do |locale|
let(:user) { FactoryGirl.build(:user, locale: locale.to_s) }
let(:mail_registration) { UserMailer.registration_confirmation(user) }
it "should send registration confirmation" do
puts locale.to_yaml
mail_registration.body.encoded.should include("test") # it will return error with text which allow me to ensure that for each locale the test call only :en locale email template
end
end
end
It runs few times (as many as many locales I have), but every time it generate html for the default locale only.
When I call UserMailer.registration_confirmation(#user).deliver from controller, it works fine.
user_mailer.rb
...
def registration_confirmation(user)
#user = user
mail(to: user.email, subject: t('user_mailer.registration_confirmation.subject')) do |format|
format.html { render :layout => 'mailer'}
format.text
end
end
...
views/user_mailer/registration_confirmation.text.erb
<%=t '.thx' %>, <%= #user.name %>.
<%=t '.site_description' %>
<%=t '.credentials' %>:
<%=t '.email' %>: <%= #user.email %>
<%=t '.password' %>: <%= #user.password %>
<%=t '.sign_in_text' %>: <%= signin_url %>
---
<%=t 'unsubscribe' %>
I repeat - it works fine for all locales.
I have the question only about rspec tests for it.
I think you may have to wrap your test in a describe/context block to allow the it block to see your let variables:
require "spec_helper"
describe UserMailer do
I18n.available_locales.each do |locale|
describe "registration" do
let(:user) { FactoryGirl.build(:user, locale: locale.to_s) }
let(:mail_registration) { UserMailer.registration_confirmation(user) }
it "should send registration confirmation" do
puts locale.to_yaml
mail_registration.body.encoded.should include("test")
end
end
# ...
end
# ...
end
As for why, perhaps this StackOverflow answer on let variable scoping may help.
Edit
Is the issue that you've assigned a locale to your user, but you don't pass it into the mail method anywhere? Perhaps this StackOverflow answer would be of reference. Hopefully one of the two answers there would be relevant in your situation. Here's my simple attempt at adapting the first answer there to your situation (untested obviously):
user_mailer.rb
...
def registration_confirmation(user)
#user = user
I18n.with_locale(user.locale) do
mail(to: user.email,
subject: t('user_mailer.registration_confirmation.subject')) do |format|
format.html { render :layout => 'mailer' }
format.text
end
end
end
...
You probably need to specify the locale, as in:
mail_subscribe.body.encoded.should include(t('user_mailer.subscribe_confirmation.stay', locale: locale))
You can also try adding I18n.locale = user.locale right before the mail call in the registration_confirmation method.

following ruby.railstutorial.org/ and getting failing test

I am using Ruby 1.9.2 and Rails 3.0.3
I am consistently getting failing test errors within this tutorial such as:
1) UsersController GET 'show' should show the user's micropost
Failure/Error: get :show, :id => #user
undefined method `model_name' for NilClass:Class
# ./app/views/users/show.html.erb:10:in `_app_views_users_show_html_erb__2659465448390875355_2173812560_4463455946834160058'
# ./spec/controllers/users_controller_spec.rb:39:in `block (3 levels) in <top (required)>'
show.html.erb:10 is:
<% unless #user.microposts.empty? %>
<table class="microposts" summary="User microposts">
<%= render #microposts %> #line 10
</table>
<%= will_pagination #microposts %>
<% end %>
users_controller_spec.rb:39 is:
describe "GET 'show'" do
before(:each) do
#user = Factory(:user)
end
.
.
.
it "should show the user's micropost" do
mp1 = Factory(:micropost, :user => #user, :content => "Foo bar")
mp2 = Factory(:micropost, :user => #user, :content => "Baz quux")
get :show, :id => #user
response.should have_selector("span.content", :content => mp1.cntent)
response.should have_selector("span.content", :content => mp2.content)
end
and my app/controllers/users_controller.rb where is defines micropost is:
def show
#user = User.find(params[:id])
#microposts = #user.microposts.paginate(:page => params[:page])
#title = #user.name
end
any help would be greatly appreciated. I have a total of 14 errors. My other errors are about
Failure/Error: get :edit, :id => #user
#controller is nil: make sure you set it in your test's setup method.
and
Failure/Error: test_sign_in(wrong_user)
undefined method `sign_in' for nil:NilClass
I am also using Factory as a test sign in. Im not sure if this could be a problem. I mention this because some of the errors are:
9) authentication of edit/update pages GET 'index' for signed-in users should have the right title
Failure/Error: #user = test_sign_in(Factory(:user))
Validation failed: Email has already been taken
# ./spec/controllers/users_controller_spec.rb:222:in `block (4 levels) in <top (required)>'
If you need to see anymore code please let me know.
If someone could direct me to a place to learn more about debugging, that would be a big help as well.
For error 1 try checking your filenames for spelling and case.
For error 9 try double checking which do..end you paste your code into.
Working code for the tutorial can be found here https://github.com/railstutorial

exception_notification for delayed_job

Is there a exception_notification-like gem for delayed_job?
Preferably that works with REE-1.8.7 and Rails 2.3.10.
I've done something like this in the past for delayed job rake tasks:
require 'action_mailer'
class ExceptionMailer < ActionMailer::Base
def setup_mail
#from = ExceptionNotifier.sender_address
#sent_on = Time.now
#content_type = "text/plain"
end
def exception_message(subject, message)
setup_mail
#subject = subject
#recipients = ExceptionNotifier.exception_recipients
#body = message
end
end
namespace :jobs do
desc "sync the local database with the remote CMS"
task(:sync_cms => :environment) do
Resort.sync_all!
result = Delayed::Job.work_off
unless result[1].zero?
ExceptionMailer.deliver_exception_message("[SYNC CMS] Error syncing CMS id: #{Delayed::Job.last.id}", Delayed::Job.last.last_error)
end
end
end
Include this module in classes which are to be delayed:
require 'exception_notifier'
module Delayed
module ExceptionNotifier
# Send error via exception notifier
def error(job, e)
env = {}
env['exception_notifier.options'] = {
:sections => %w(backtrace delayed_job),
:email_prefix => '[Delayed Job ERROR] ',
:exception_recipients => %w(some#email.com),
:sender_address => %(other#email.com)
}
env['exception_notifier.exception_data'] = {:job => job}
::ExceptionNotifier::Notifier.exception_notification(env, e).deliver
end
end
end
and create a template for the notification in app/views/exception_notifier/_delayed_job.text.erb:
Job name: <%= #job.name %>
Job: <%= raw #job.inspect %>
* Process: <%= raw $$ %>
* Server : <%= raw `hostname -s`.chomp %>

Resources