Delayed job and Mandrill: uninitialized constant Mandrill::API - ruby-on-rails-3

I have mailer service where users can upload an .xls file with emails and some other user related data to send an email campaign.
I was having some timeout issues since it takes some seconds to process (as I do some validation and configuration for each email to be sent, eg: save records to database, check if an email was sent in the last 30 days, create personalised html code for each email (to create links that contain the email address as a parameter, etc).
After some research, moving this to a delayed job seemed reasonable, as suggested in this rails cast. The only problem is that I am having an error that says uninitialized constant Mandrill::API, it seems that when I run the job, the call require 'mandrill' doesn't work.
I created the task in my model file. Something like this
class Mailer < ActiveRecord::Base
attr_accessible :email, :lastname, :name
def self.send_mail(emails)
[...a lot of code here...]
require 'mandrill'
m = Mandrill::API.new ENV['MANDRILL_APIKEY']
message = {
:subject=> template.subject,
:from_name=> template.from_name,
:from_email=> from + "#" + email_domain,
:to=>mails,
:global_merge_vars=> [
{ :name => 'GREETING', :content => template.greeting},
{ :name => 'CONT1', :content => template.message},
{ :name => 'IMAGE', :content => image_url},
],
:html=>email_template,
:preserve_recipients => false,
:merge_vars => email_contents,
}
sending = m.messages.send message
end
end
from my controller I call Mailer.send_mails(emails) and it works just fine, but if I call Mailer.delay.send_mails(emails) I get the error. How can I fix this?
I have tried adding require 'mandrill' at the beginning of the class, before and after class Mailer < ActiveRecord::Base but nothing seems to work

Make sure to restart the delayed_job daemon to pick up any code changes. It does not auto-reload like the Rails development environment does.

Related

rspec vs 'url_validation' gem

I'm struggling with rspec as a new Rails person and I have a need to validate a url passed into Active Record. This is probably due to my ignorance so pls point me in the right direction. The video_url is a string field which I'd like to validate as being a valid URL. Looking around, I chose this gem because it appeared to be fully tested in rspec. For my test I didn't see how I could incorporate his validation test into my model test.
In rails console, I created a Post object and ensured that if I put a bogus URL that I knew would not be found, I would get an error. The curious thing is that attempting to replicate this in a test with the gem installed fails the test because it finds no errors. I expected an error of some kind as I got in console. My question is what am I doing wrong in that it gets no errors? I've made several attempts to triangulate what might be causing it but the gem doesn't seem to work in rspec? I would have thought that if I could get it to work in console, I can get it to work in rspec?
post.rb
class Post < ActiveRecord::Base
attr_accessible :body, :title, :image, :video_title, :video_url
validates_presence_of :title, :body, :author
validates :video_url, :presence => true, :if => :video_title_present?, :url => {
:check_path => [ 300..399, 400..499, 500..599 ], :allow_nil => true,
:url_not_accessible_message => "must be valid.",
:invalid_url_message => "must be valid.",
:url_invalid_response_message => "must be valid."}
def video_title_present?
!self.video_title.blank?
end
belongs_to :author, class_name: "User"
end
post_spec.rb
before do
#post = Post.new(title: "foo", body: "my body here")
end
describe "validates with video links" do
it "validates with video url and video title" do
#post.video_url = "http://heckitoqi.com"
#post.video_title = "my title"
#post.should have_at_least(1).error_on(:video_url)
end
end
Output in console:
Failure/Error: #post.should have_at_least(1).error_on(:video_url)
expected at least 1 error on :video_url, got 0
In some of my errors, I attempted a more open-ended error, but it fails by not catching any errors.
Here is a short version of my smoke test of the model using Rails console:
u = User.first
p = Post.new(title: "title", body: "body", video_title: "vtitle", video_url: "http://heckitoqi.com")
p.author = u
p.save!
>> HTTPI GET request to heckitoqi.com (net_http)
>> ActiveRecord::RecordInvalid: Validation failed: Video url must be valid.
If I can get it to validate in the console, then my implementation of the test is at fault, right? I just don't see what I'm doing wrong. thanx, sam

Rails 3 mail not working, however devise mail does works

I have a rails 3.2.3 application that works fine and delivers devise's created mail messages as, registration confirmation and password forget mail messages to set a new password.
However I have a different places that I want to deliver mail notifications.
This is my Notifiermodel.
# encoding: utf-8
class Notifier < ActionMailer::Base
default from: "no-reply#domain.com"
default to: "admin#domain.com"
def new_post_submitted(post)
#post = post
mail(subject: "Anúncio enviado: #{#post.title}")
end
def new_message(message)
#message = message
mail(subject: "Mensagem de contato: #{#message.subject}")
end
end
and the controller calls:
def create
#message = Message.new(params[:message])
if #message.valid?
Notifier.new_message(#message).deliver
redirect_to(root_path, :notice => "Obrigado. Sua Mensagem enviada com sucesso")
else
flash.now.alert = "Por favor preencha todos os campos."
render :new
end
end
The log output says it was delivered:
Started POST "/contato" for 187.57.102.168 at 2012-08-31 11:28:51 +0900
Processing by ContactController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"TVdmDYCA4x3JVi+9pMcpY7OSU/P1lE9enLiFJlK9W1M=", "message"=>{"name"=>"kleber", "email"=>"test#gmail.com", "subject"=>"teste", "body"=>"hello there"}, "commit"=>"Enviar"}
Rendered notifier/new_message.html.erb (0.1ms)
Sent mail to admin#domain.com (152ms)
Redirected to http://www.domain.com/
Completed 302 Found in 158ms (ActiveRecord: 0.0ms)
And the following configuration on my config/production.rbfile.
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
:address => "localhost",
:port => 25,
:domain => "domain.com",
:authentication => :login,
:user_name => "admin#domain.com",
:password => "mypassword",
:enable_starttls_auto => false
}
Any clue on what is happening here?
Here are the settings that work in my production.rb file.
ActionMailer::Base.smtp_settings = {
:address => 'mail.domain.com',
:port => 587,
:domain => 'domain.com',
:authentication => :login,
:user_name => 'postmaster#domain.com',
:password => 'password'
}
Not sure you have to specify delivery_method?
ActionMailer::Base.delivery_method = :smtp
I don't have that in my config and everything works properly.
In the rails API http://api.rubyonrails.org/ ActionMailer section there is an option to set a delivery error.
raise_delivery_errors - Whether or not errors should be raised if the email fails to be delivered.
You could try that to further troubleshoot the problem.
First, make sure you haven't turned off deliveries somewhere else in the environment file:
# the default is true anyway, so if you don't see it anywhere in
# the file, you should be okay
config.action_mailer.perform_deliveries = true
I would next try changing the delivery method to either :sendmail or :file. If you have sendmail installed and configured on your system (at least a development system), then you should receive the e-mails you send. I was surprised at one point to discover that sendmail worked out of the box on OS X. I'm not sure if you'd find the same on CentOS.
If you don't have sendmail or don't want to configure it, use the :file delivery method to dump the e-mails to a file on the filesystem.
At this point, if the e-mails don't deliver via sendmail or file, you know there's a problem further up the stack. If they do deliver, then the problem is your SMTP configuration. Try using a known working SMTP server (such as your Gmail account). If that works, then you know it's a problem with the SMTP server running on localhost and not with ActionMailer.

Validation on missing attributes on update_attributes

The question is very simple, does update_attributes validates every possible validation of the model, even if I don't want to update some of the attributes?
I have a edit view, where the user might change his password, but only if he passes it, i.e., if it's blank the password would not change.
So I do the following in the controller:
def update
params[resource_name].delete(:password) if params[resource_name][:password].blank?
params[resource_name].delete(:password_confirmation) if params[resource_name][:password_confirmation].blank?
params[resource_name].delete(:current_password) if params[resource_name][:current_password].blank?
if resource.update_attributes(params[resource_name])
...
end
end
I defined the following validation on the model:
validates :password,
:length => { :within => 6..40 }
So whenever i use call the update I get an error saying that the password is too short
Ps.: I'm using Devise to deal it this.
EDIT: Do any of you know if Devise already have any validation on the password? Cause, I removed the validation and it worked in the right way, but if I put a short password it still show a validation, saying it's too short.
Yes, Devise does provide validations on password if you've passed :validatable to the devise method in your model. The default configuration for password length is 6..128. You can override this in config/initializers/devise.rb (around line 101).
You can remove :validatable from your model and write your own validations if you prefer. If you do this and don't want the validation to run if the password isn't passed to update_attributes, then do something like this:
validates :password, :presence => true, :if => lambda { new_record? || !password.nil? }

rails3 routing and yaml based API, using devise and cancan

I have an application that will have an API, with a /api/v1/ namespace:
namespace :api do
namespace :v1 do
resources :gateways do
resources :mappings do
# maybe more stuff
end
end
end
end
my application uses devise and cancan.
My mappings controller down in app/controllers/api/v1/mappings_controller.rb works correctly from rspec test cases if I leave out :format=>:yaml (asking for HTML, and getting a 406).
If I ask for :yaml, devise seems to think that my test user is not allowed.
My test case is stupid simple:
describe "Agent access to mappings" do
it "gets a list of mappings that includes test_user mapping" do
#test_agent = users(:firewallagent)
sign_in(#test_agent)
get :show, {:gateway_id => 1, :id => 2} #, :format => :yaml
assert_response 200
end
end
I can't see anything in devise/warden which would be format specific, but maybe I've missed it.
The fault was that :format=>:yaml needs to go into the first hash, rather than into the second hash for get. So:
get :show, {:gateway_id => 1, :id => 2, :format => :yaml}

"Email is already taken" error when user logs in with client_side_validations and devise

I am trying to use both client_side_validations and devise in my Rails app, and get a weird bug in the log in form.
It's says that the email has already been taken and doesn't let the user to log in :)
Email is used as the login.
This is only when I set the :validate => true.
When I turn off the setting :validate => true, the log in is performed successfully.
What might cause this problem?
I got the answer from the author of the client_side_validations:
For login form you don't want to have the uniqueness validator. So you'll need to do something like:
f.text_field :email, :validate => { :uniqueness => false }
From what I've understood this is the workaround because of the conditional validations in devise.