delayed_job missing method - ruby-on-rails

I add a job to delayed job but when I run it I have a NoMethod error
Delayed::Job.last
=> #Delayed::Backend::MongoMapper::Job _id: BSON::ObjectId('5266f28aa1cba6257b000001'), attempts: 0, created_at: Tue, 22 Oct 2013 23:47:54 CEST +02:00, failed_at: nil, handler: "--- !ruby/struct:Delayed::PerformableMethod \nobject: !ruby/object:Module {}\n\nmethod: :notify_all_with_review_reminder_due!\nargs: []\n\n", last_error: nil, locked_at: nil, locked_by: nil, priority: 75, run_at: Tue, 22 Oct 2013 23:47:54 CEST +02:00, updated_at: Tue, 22 Oct 2013 23:47:54 CEST +02:00>
Delayed::Job.last.invoke_job
NoMethodError: undefined method `notify_all_with_review_reminder_due!' for #Module:0x124781cf0>
Looks like he is not able to serialize the correct object (it is a module).
Googling around I found the suggestion to require the module in config/inizializers but this is not working for me.
Any idea?

I had hit similar problem, and at time of writing this I have not found any other solution besides the "require" but in my case I was trying to queue the module class, so I just wrapped it with class and it wroks now.
before:
module GlobalModule
def self.some_method
end
end
Delayed::Job failing with similar error when calling GlobalModule::delay.some_method
after:
module GlobalModule
class Wrapper
def self.some_method
end
end
end
GlobalModule::Wrapper.delay.some_method

Related

rails PaperTrail gem causing duplicate version entries starting with version 6

Here is a piece of rspec code defining a risk_action :
let(:risk_action) {
risk_action = risk.risk_actions.new({name: 'action 1', user: user, action_status_id: created.id, due_date: '2018-02-10', owner_email: user.email, org: org})
risk_action.org = org
risk_action.assigned_to = user
risk_action.save!
risk_action
}
Both in rails 4 & 5, this behaves as I expect (it creates and persists the risk_action without error). Later in the rspec, I have a test case which runs a controller method and eventually calls this risk_action. I can confirm nothing has manipulated the object in the meantime (largely because my test case which is checking it via papertrail is working correctly) :
it "correctly assigns the Paper_Trail whodunnit type", versioning: true, focus: true do
session = RiskActionSession.create({risk_action: risk_action})
expect(session).to be_valid
expect(session.status).to eq('CREATED')
jwt = session.generate_jwt
#request.env["HTTP_AUTHORIZATION"] = "JWT #{jwt}" # <-- DOES NOT WORK
get :update_action, id: session.id, risk_action: {action_status_id: closed.id}, token: jwt
expect(response.status).to eq(200)
# there should be 2 versions [create, update]
versions = risk_action.versions
expect(versions.length).to eq(2)
# 1 update event
ver = versions.where(event: "update")
expect(ver.length).to eq(1)
#whodunnit_type should be set to 'User'
expect(ver[0].whodunnit_type).to eq("User")
end
end #describe "update_action [PUT]" do
Then, after retrieving the risk_action and calling versions on it, I would expect to see a single create entry. Instead, I see two, precise duplicated except for the id (of the version object) :
[#<PaperTrail::Version:0x0000000006b1a930
id: 24328,
item_type: "RiskAction",
item_id: 44074,
event: "create",
whodunnit: "543076",
object: nil,
created_at: Mon, 15 Aug 2022 16:14:45 UTC +00:00,
object_changes:
"---\nname:\n- \n- action 1\nuser_id:\n- \n- 543076\naction_status_id:\n- \n- 66607\ndue_date:\n- \n- '2018-02-10 00:00:00'\nowner_email:\n- ''\n- foo1#example.com\norg_id:\n- \n- 642273\nassigned_to_id:\n- \n- 543076\nassigned_to_type:\n- \n- User\nid:\n- \n- 44074\n",
whodunnit_type: nil,
comments: nil,
transaction_id: 24322>,
#<PaperTrail::Version:0x0000000006b1a430
id: 24329,
item_type: "RiskAction",
item_id: 44074,
event: "create",
whodunnit: "543076",
object: nil,
created_at: Mon, 15 Aug 2022 16:14:45 UTC +00:00,
object_changes:
"---\nname:\n- \n- action 1\nuser_id:\n- \n- 543076\naction_status_id:\n- \n- 66607\ndue_date:\n- \n- '2018-02-10 00:00:00'\nowner_email:\n- ''\n- foo1#example.com\norg_id:\n- \n- 642273\nassigned_to_id:\n- \n- 543076\nassigned_to_type:\n- \n- User\nid:\n- \n- 44074\n",
whodunnit_type: nil,
comments: nil,
transaction_id: 24322>]
This behaviour starts occurring with the papertrail gem version 6 on rails 4.2.10. The behaviour continues into rails 5.2.8 and papertrail gem versions 9 thru 11, the latter of which is where I'm trying to end up.
I am not sure why the behaviour begins here, there is nothing in the changelog (at least, that's obvious to me) why this would be the case. Any help is appreciated -- thank you.

is it possible to override built-in Ruby methods?

I am working on a problem where I have to pass an rpsec test. The problem is that the method is using the same name as a built in ruby method .count
given that I cannot change the rspec test, is it possible to override .count to behave differently? if not, is there a better way to get around this?
here is the rspec test I am trying to pass
subject = FinancialSummary.one_day(user: user, currency: :usd)
expect(subject.count(:deposit)).to eq(2)
my code:
class FinancialSummary
def self.one_day(user: user, currency: currency)
one_day_range = Date.today.beginning_of_day..Date.today.end_of_day
find_transaction(user.id, currency).where(created_at: one_day_range)
end
def self.find_transaction(user_id, currency)
Transaction.where(user_id: user_id,
amount_currency: currency.to_s.upcase
)
end
end
output:
[#<Transaction:0x00007f9b39c2e9b8
id: 1,
user_id: 1,
amount_cents: 1,
amount_currency: "USD",
category: "deposit",
created_at: Sat, 10 Mar 2018 18:46:53 UTC +00:00,
updated_at: Sat, 10 Mar 2018 18:46:53 UTC +00:00>,
#<Transaction:0x00007f9b3d0dbc38
id: 2,
user_id: 1,
amount_cents: 2000,
amount_currency: "USD",
category: "deposit",
created_at: Sat, 10 Mar 2018 18:47:43 UTC +00:00,
updated_at: Sat, 10 Mar 2018 18:47:43 UTC +00:00>,
#<Transaction:0x00007f9b3d0b3fa8
id: 7,
user_id: 1,
amount_cents: 1200,
amount_currency: "USD",
category: "withdraw",
created_at: Mon, 05 Mar 2018 02:22:42 UTC +00:00,
updated_at: Tue, 06 Mar 2018 18:48:20 UTC +00:00>]
it is printing out, what I believe to be the correct information, up until the test attempts to count the transactions by their category: 'deposit'. Then I get this error message:
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: deposit: SELECT COUNT(deposit) FROM "transactions" WHERE "transactions"."user_id" = ? AND "transactions"."amount_currency" = ?
EDITED FOR MORE INFO
Some Assumptions Were Made in the Writing of this answer and modifications may be made based on updated specifications
Overriding count is a bad idea because others who view or use your code will have no idea that this is not the count they know and understand.
Instead consider creating a scope for this like
class FinancialSummary < ApplicationRecord
scope :one_day, ->(user:,currency:) { where(user: user, currency: currency) } #clearly already a scope
scope :transaction_type, ->(transaction_type:) { where(category: transaction_type) }
end
then the test becomes
subject = FinancialSummary.one_day(user: user, currency: :usd)
expect(subject.transaction_type(:deposit).count).to eq(2)
SQL now becomes:
SELECT COUNT(*)
FROM
"transactions"
WHERE
"transactions"."user_id" = ?
AND "transactions"."amount_currency" = "usd"
AND "transactions"."category" = "deposit"
Still very understandable and easy to read without the need to destroy the count method we clearly just used.
It's not clear what object the count message is being sent to because I don't know what FinancialSummary.one_day(user: user, currency: :usd) returns, but it seems like you are saying count is a method on whatever it returns, that you can't change. What does FinancialSummary.one_day(user: user, currency: :usd).class return?
Perhaps one solution would be to alias it on that object by adding alias_method :count, :account_count and then in your test calling expect(subject.account_count(:deposit)).to eq(2)
It would be easier if you could post the FinancialSummary#one_day method in your question.

Comparing ranges of datetimes in Ruby on Rails against one-another

Right now I'm trying to see if a certain show's start and end times overlap another show that's currently recording => true where 'show' is the TV show the user wants to record.
def self.record_show
shows = Box.first.shows.where(:recording => true).flatten
show_start_and_end_times = shows.collect {|x| x.start_time..x.end_time}
current_show_time = show.start_time..show.end_time
overlap = show_start_and_end_times.select {|c| current_show_time.overlaps?(c)}
if overlap.present?
nil
else
show.update_attributes(:recording => true)
show.save
end
end
It runs the method, but I'm having difficulty figuring out how to get it so that it finds the actual currently recording show that's causing the overlap. So for example, let's say in 'shows' I currently have two shows:
[#<Show id: 181, box_id: 78, title: "The Fox", channel: 22, single_recording: true, created_at: "2014-08-12 19:55:49", updated_at: "2014-08-12 20:09:24", start_time: "2014-08-12 19:55:49", end_time: "2014-08-12 20:25:49", recording: true>, #<Show id: 186, box_id: 78, title: "Funniest Home Videos", channel: 45, single_recording: true, created_at: "2014-08-12 19:55:49", updated_at: "2014-08-12 20:09:27", start_time: "2014-08-12 23:20:49", end_time: "2014-08-13 00:20:49", recording: true>]
In show_start_and_end_times I have:
[Tue, 12 Aug 2014 19:55:49 UTC +00:00..Tue, 12 Aug 2014 20:25:49 UTC +00:00, Tue, 12 Aug 2014 23:20:49 UTC +00:00..Wed, 13 Aug 2014 00:20:49 UTC +00:00]
In current_show_time I have:
Tue, 12 Aug 2014 19:55:49 UTC +00:00..Tue, 12 Aug 2014 20:55:49 UTC +00:00
Which means that in overlap I have the start_time..end_time of the first show_start_and_end_times show, which is the one that is causing the overlap:
[Tue, 12 Aug 2014 19:55:49 UTC +00:00..Tue, 12 Aug 2014 20:25:49 UTC +00:00]
I tried comparing the two times against one-another:
(shows.first.start_time..shows.first.end_time) == (overlap.first)
Which gives me false, even though the times are exactly the same. How can I compare the overlap time against the shows list to figure out which show is causing the overlap?
You'll wand to check out:
http://guides.rubyonrails.org/active_record_querying.html
Using info from that you might be able to do something like:
def self.record_show
overlapping_shows = Box.first.shows.where(recording: true).where("start_time <= :show_end AND end_time >= :show_start", {show_start: show.start_time, show_end: show.end_time}).flatten
if overlapping_shows.present?
nil
else
show.update_attributes(:recording => true)
show.save
end
end
This is a pretty common problem, and I'd recommend checking out this SO question for general algorithm advice on how to do the overlap checking:
Determine Whether Two Date Ranges Overlap
UPDATE:
I would change it to something like this:
shows = Box.first.shows.where(:recording => true).flatten
overlapping_show = nil
current_show_time = show.start_time..show.end_time
shows.each do |s|
if current_show_time.overlaps?(s.start_time..s.end_time)}
overlapping_show = s
break # you could alternatively return an array of overlapping
# if you anticipate more than 1 will overlap
end
end
if overlap.present? #...

Most proper way to use inherited classes with shared relations?

I have the TestVisual class that is inherited by the Game class :
class TestVisual < Game
include MongoMapper::Document
end
class Game
include MongoMapper::Document
belongs_to :maestra
key :incorrect, Integer
key :correct, Integer
key :time_to_complete, Integer
key :maestra_id, ObjectId
timestamps!
end
As you can see it belongs to Maestra.
So I can do Maestra.first.games which returns []
But I can not to Maestra.first.test_visuals because it returns undefined method test_visuals
Since I'm working specifically with TestVisuals, that is ideally what I would like to pull, but still have it share the attributes of its parent Game class.
Is this possible with Mongo. If it isn't or if it isn't necessary, is there any other better way to reach the TestVisual object from Maestra and still have it inherit Game ?
Single Collection Inheritance (SCI) in MongoMapper auto-generates selection,
ex., the following produce the same results.
p Game.where(_type: 'TestVisual').all
p TestVisual.all
See also mongomapper/lib/mongo_mapper/plugins/sci.rb - MongoMapper::Plugins::Sci::ClassMethods#query
However, MongoMapper does not auto-generate associations for subclasses based on the base class' associations,
and I don't think that this should be expected.
Note that SCI places subclasses and base classes in the same MongoDB collection.
If this is not what you want, you should consider other mechanisms for modularity.
You can define the following method yourself for an association accessor method, perhaps this is sufficient for your purposes?
For other association methods like append or push, the parent methods are probably workable.
class Maestra
include MongoMapper::Document
key :name, String
many :games
def test_visuals
games.where(_type: 'TestVisual')
end
end
test/unit/test_visual_test.rb
require 'test_helper'
def ppp(obj)
puts obj.inspect.gsub(/, ([^#])/, ",\n\t\\1").gsub(/, #/, ",\n #")
end
class TestVisualTest < ActiveSupport::TestCase
def setup
Maestra.delete_all
Game.delete_all
end
test "inheritance" do
maestra = Maestra.create(name: 'Fiona')
maestra.games << Game.create(incorrect: 1, correct: 9, time_to_complete: 60)
maestra.games << TestVisual.create(incorrect: 2, correct: 8, time_to_complete: 61)
ppp maestra.games.to_a
ppp maestra.test_visuals.to_a
end
end
output
Run options: --name=test_inheritance
# Running tests:
[#<Game _id: BSON::ObjectId('4ff7029a7f11ba6e43000002'),
_type: "Game",
correct: 9,
created_at: Fri,
06 Jul 2012 15:22:02 UTC +00:00,
incorrect: 1,
maestra_id: BSON::ObjectId('4ff7029a7f11ba6e43000001'),
time_to_complete: 60,
updated_at: Fri,
06 Jul 2012 15:22:02 UTC +00:00>,
#<TestVisual _id: BSON::ObjectId('4ff7029a7f11ba6e43000003'),
_type: "TestVisual",
correct: 8,
created_at: Fri,
06 Jul 2012 15:22:02 UTC +00:00,
incorrect: 2,
maestra_id: BSON::ObjectId('4ff7029a7f11ba6e43000001'),
time_to_complete: 61,
updated_at: Fri,
06 Jul 2012 15:22:02 UTC +00:00>]
[#<TestVisual _id: BSON::ObjectId('4ff7029a7f11ba6e43000003'),
_type: "TestVisual",
correct: 8,
created_at: Fri,
06 Jul 2012 15:22:02 UTC +00:00,
incorrect: 2,
maestra_id: BSON::ObjectId('4ff7029a7f11ba6e43000001'),
time_to_complete: 61,
updated_at: Fri,
06 Jul 2012 15:22:02 UTC +00:00>]
.
Finished tests in 0.026661s, 37.5080 tests/s, 0.0000 assertions/s.
1 tests, 0 assertions, 0 failures, 0 errors, 0 skips

Weird created_at behavior

I've set config.time_zone = 'UTC' in environment.rb, and yet still I get some weird behavior with Rails' built-in datetime fields:
>> Time.now
=> Sun Jun 21 17:05:59 -0700 2009
>> Feedback.create(:body => "testing")
=> #<Feedback id: 23, body: "testing", email_address: nil, name: nil, created_at: "2009-06-22 00:06:09", updated_at: "2009-06-22 00:06:09">
>> Time.parse(Feedback.last.created_at.to_s)
=> Mon Jun 22 00:06:09 UTC 2009
Any thoughts?
It looks like it's properly setting the timezone in the ActiveRecord object, so I don't think you need to worry too much. If you want to force your timestamp from Rails to use UTC, you can use Time.utc.
Time.now.utc
=> Mon Jun 22 00:54:21 UTC 2009

Resources