Resque Worker: Objects and methods not available in worker - ruby-on-rails

I have the following worker in my web app
class TweetSender
#queue = :tweets_queue
def self.perform(tweet_id)
message = Tweet.where(:status_id => 0).order(:created_at, :id).limit(1)
message.update_attribute(status_id = 1)
$client.update(message.text)
end
end
It gets schedueled by the following resque-scheduler tweet_scheduler.yml
tweet_sender:
cron: "0 20 * * * Europe/Stockholm"
class: "TweetSender"
queue: tweets_queue
args: tweet_id
description: "This job sends daily tweets from the content db"
Which gets defined by he resque.rake
require 'resque/tasks'
require 'resque/scheduler/tasks'
task 'resque:setup' => :environment
namespace :resque do
task :setup do
require 'resque'
end
task :setup_schedule => :setup do
require 'resque-scheduler'
Resque.schedule = YAML.load_file('tweet_schedule.yml')
require 'jobs'
end
task :scheduler => :setup_schedule
end
In the resque web interface I get the following error
Exception
NoMethodError
Error
undefined method `update_attribute' for #<Tweet::ActiveRecord_Relation:0x839ca814>
/home/jan/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/relation/delegation.rb:136:in `method_missing'
/home/jan/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/relation/delegation.rb:99:in `method_missing'
/home/jan/Documents/social/app/jobs/tweet_sender.rb:6:in `perform'
I alos tried implementing the tweet_sender.rb without the update_atttribute methods like so:
class TweetSender
#queue = :tweets_queue
def self.perform(tweet_id)
message = Tweet.where(:status_id => 0).order(:created_at, :id).limit(1)
message.status_id = 1
message.save
$client.update(message.text)
end
end
And the get the following error:
Exception
NoMethodError
Error
undefined method `status_id=' for #<Tweet::ActiveRecord_Relation:0x83195bf8>
/home/jan/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/relation/delegation.rb:136:in `method_missing'
/home/jan/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/relation/delegation.rb:99:in `method_missing'
/home/jan/Documents/social/app/jobs/tweet_sender.rb:6:in `perform'
Why are my methods and the standard rails emthods no available in my worker? Do I need to explicitly require them somewhere?

limit returns an instance of ActiveRecord::Relation.
What you really want to get is an instance of Tweet model.
Use first:
message = Tweet.where(status_id: 0).order(:created_at, :id).first

Related

Exception error="uninitialized constant V1" using Sneakers

I'm trying to implement Sneakers, but I'm having some issues. Below you can find the code which subscribers to my queue and the actual error.
require 'sneakers'
require 'jwt'
require 'redis'
require 'json'
$redis = Redis.new(url: ENV['REDIS_URL'], password: ENV['REDIS_PASSWORD'])
class Processor
include Sneakers::Worker
QUEUE_NAME = :my_queue
from_queue QUEUE_NAME
def work(msg)
message = JSON.parse(msg)
if message["type"] == "error"
$redis.incr "processor:#{err["error"]}"
end
controller = Object.const_get message['controller']
action = message['method']
controller.public_send(action, message['msg'])
ack!
end
end
Error:
[Exception error="uninitialized constant V1" error_class=NameError worker_class=Processor
The msg object
{\"controller\":\"V1::x::yController\",\"method\":\"my_method"\}
Any help is welcome, thank you!
Update
Even getting a simple Model such as my User is resulting into the same error.
[Exception error="uninitialized constant User"
I'm running the sneakers worker like so:
sneakers work UserCreate --require app/workers/user_create.rb

Rails + Rspec: Test says value of variable is nil, console says otherwise

I have a test that's failing for a custom non active record class I'm writing:
test:
describe "#xml_for_initial_request" do
it "calls the access_request method" do
ups_shipping = UpsShipping.new
ups_shipping.should_receive(:credentials)
ups_shipping.print_xml
end
end
console:
Failures:
1) UpsShipping#xml_for_initial_request calls the access_request method
Failure/Error: ups_shipping.print_xml
NoMethodError:
undefined method `to_xml' for nil:NilClass #<-- FAILURE HERE
# ./app/models/ups_shipping.rb:14:in `print_xml'
# ./spec/models/ups_shipping_spec.rb:465:in `block (3 levels) in <top (required)>'
Finished in 0.45009 seconds
1 example, 1 failure
This occurs in this model:
require 'net/https'
require 'uri'
class UpsShipping
attr_reader :products, :purchase
def initialize(options = {})
#products = options.fetch(:products, [])
#purchase = options[:purchase]
end
def print_xml
xml = ''
xml << credentials.to_xml #<-- ERROR OCCURS HERE
return xml
end
def credentials #<-- CREDENTIALS COMES FROM HERE
{
"AccessLicenseNumber" => UPS_API["access_key"],
"UserId" => UPS_API["user_id"],
"Password" => UPS_API["password"]
}
end
....
However, when I try this in the console in the test environment it works:
Nets-Mac-Pro:myproject emai$ RAILS_ENV=test bundle exec rails c --sandbox
/Users/emai/.rvm/gems/ruby-1.9.3-p362#myproject/gems/ruby-debug-ide-0.4.18/lib/ruby-debug-ide/command.rb:27: warning: already initialized constant DEF_OPTIONS
Loading test environment in sandbox (Rails 3.2.13)
Any modifications you make will be rolled back on exit
1.9.3p362 :001 > ups_shipping = UpsShipping.new
=> #<UpsShipping:0x007feb0c974790 #products=[], #purchase=nil>
1.9.3p362 :002 > ups_shipping.print_xml
=> "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hash>\n <AccessLicenseNumber>xxxxx</AccessLicenseNumber>\n <UserId>xxxx</UserId>\n <Password>xxx</Password>\n</hash>\n"
1.9.3p362 :003 > ups_shipping.credentials
=> {"AccessLicenseNumber"=>"xxxx", "UserId"=>"xxxx", "Password"=>"xxxx"}
What's the deal???
should_receive is intercepting the method call and not calling the original and, by default, returning nil. Add a call to and_call_original:
ups_shipping.should_receive(:credentials).and_call_original

Uninitialized Constant error Loading a class/module in a Rails initializer

I'm working on integrating Stripe's webhooks into a Rails app using https://github.com/integrallis/stripe_event. I'm struggling to get my code to working according to the example in the gem's docs whereby an initializer is used to dictate which code responds to a particular event. It seems that Rails isn't (auto)loading my module in the initializer.
I'm configuring the autoload path properly:
# config/application.rb
config.autoload_paths += %W(#{config.root}/lib)
The stripe initializer:
#config/initializers/stripe.rb
stripe_config = YAML.load_file(Rails.root.join('config', 'stripe.yml'))[Rails.env]
Stripe.api_key = stripe_config["secret_key"]
STRIPE_PUBLIC_KEY = stripe_config["publishable_key"]
StripeEvent.setup do
# Not sure if I need this to load my module
require 'stripe_event_handlers' # => true
subscribe 'customer.subscription.created' do |event|
StripeEventHanders.handle_customer_subscription_created(event) # Define subscriber behavior
end
end
Here's my custom module (though I've tried it as a class too):
#lib/stripe_event_handlers.rb
module StripeEventHandlers
def handle_customer_subscription_created(event) # Define subscriber behavior
puts event
end
end
This is my test:
require 'test_helper'
# --- Run this in the console to get event response for mocking ---
#serialized_object = YAML::dump(Stripe::Event.retrieve('evt_0Cizt88YP0nCle'))
#filename = Rails.root.join('test/fixtures/stripe_objects', 'customer_subscription_created.yml')
#File.open(filename, 'w') {|f| f.write(serialized_object) }
class StripeEvent::WebhookControllerTest < ActionController::TestCase
def test_mock_event
event_id = 'evt_0Cizt88YP0nCle'
event = YAML.load_file(Rails.root.join('test/fixtures/stripe_objects', 'customer_subscription_created.yml'))
Stripe::Event.expects(:retrieve).with(event_id).returns(event)
assert_equal Stripe::Event.retrieve(event_id), event
end
def test_customer_subscription_created_webhook
event_id = 'evt_0Cizt88YP0nCle'
event = YAML.load_file(Rails.root.join('test/fixtures/stripe_objects', 'customer_subscription_created.yml'))
Stripe::Event.expects(:retrieve).at_most(2).with(event_id).returns(event)
# This should be a raw post request but that doesn't seem to come through
# on the stripe_event / rails side in the params hash. For testing
# purposes, we can just use a get request as the route doesn't specify an
# HTTP method.
get :event, :use_route => :stripe_event, :id => event_id
assert_response :success
end
end
And here's my test result failure:
StripeEvent::WebhookControllerTest
ERROR (0:00:00.043) test_customer_subscription_created_webhook
uninitialized constant StripeEventHanders
# config/initializers/stripe.rb:10:in `block (2 levels) in <top (required)>'
PASS (0:00:00.053) test_mock_event
Finished in 0.055477 seconds.
2 tests, 1 passed, 0 failures, 1 errors, 0 skips, 2 assertions
You are just missing the letter l in StripeEventHandlers.
subscribe 'customer.subscription.created' do |event|
StripeEventHanders.handle_customer_subscription_created(event)
end
Also, handle_customer_subscription_created should be defined as a class method:
module StripeEventHandlers
def self.handle_customer_subscription_created(event) # Define subscriber behavior
puts event
end
end

Rails Resque undefined method error in external module

I'm having trouble calling methods from an included module inside a resque worker. In the example below, I keep getting undefined method errrors when I attempt to call the say method inside the worker (which is in the TestLib module). I've reduced the code down to bare basics to illustrate the issue:
Controller
(/app/controllers/test_controller.rb)
class TestController < ApplicationController
def testque
Resque.enqueue( TestWorker, "HI" )
end
end
Library
(/lib/test_lib.rb)
module TestLib
def say( word )
puts word
end
end
Worker
(/workers/test_worker.rb)
require 'test_lib'
class TestWorker
include TestLib
#queue = :test_queue
def self.perform( word )
say( word ) #returns: undefined method 'say' for TestWorker:Class
TestLib::say( word ) #returns: undefined method 'say' for TestLib::Module
end
end
Rakefile
(resque.rake)
require "resque/tasks"
task "resque:setup" => :environment
I'm running resque using the following command: rake environment resque:work QUEUE='*'
Gems:
rails (3.0.4)
redis (2.2.2)
redis-namespace (1.0.3)
resque (1.19.0)
Server:
nginx/1.0.6
Anyone have any ideas as to what's going on there?
When you include a module, its methods become instance methods. When you extend, they become class methods. You just need to change include TestLib to extend TestLib and it should work.

uninitialized constant error when run my rake task, why?

I have a class which is NOT an ActiveRecord.
the class is located under lib/room/
lib/room/car_painter.rb
class ROOM::CarPainter
def paint_car
...
end
end
Then, I have a rake task:
under /lib/tasks/
/lib/tasks/new_car_painting.rake
namespace :new_car do
desc "Paint new cars"
task :paint => :environment do
painter = ROOM::CarPainter.new #ERROR HERE- uninitialized constant
painter.paint_car
end
end
When I run rake new_car:paint, I got the error message "uninitialized constant ROOM::CarPainter", Why??
--EDIT---
I also tried to use class function instead of instance function, like following:
class ROOM::CarPainter
def self.paint_car
...
end
end
and
namespace :new_car do
desc "Paint new cars"
task :paint => :environment do
ROOM::CarPainter.paint_car #ERROR HERE- uninitialized constant
end
end
But I get the same error message...why again
This is rake file.
desc 'This is just a testing rake task'
task :update_ts => :environment do |t,args|
puts 'ashish is great'
include TestLib
print_sm
end
This is lib/test_lib.rb file.
module TestLib
def print_sm
puts "Hello World in Lib Directory"
end
end
You just need to include that module.
Edited:
I guess problem is your lib/* folder loading.
Try with this in your application.rb file:
config.autoload_paths += Dir["#{config.root}/lib/**/"]
In rails you need to require from the root and rails 3 practice is the following
require Rails.root.join('path')

Resources