Weird exception with delayed_job - ruby-on-rails

Trying to queue a job with delayed_job as follows:
Delayed::Job.enqueue(BackgroundProcess.new(current_user, object))
current_user and object are not nil when I print them out. The weird thing is that sometimes refreshing the page or running the command again works!
Here is the exception trace:
Delayed::Backend::ActiveRecord::Job Columns (44.8ms) SHOW FIELDS FROM `delayed_jobs`
TypeError (wrong argument type nil (expected Data)):
/Users/.rvm/rubies/ruby-1.9.1-p378/lib/ruby/1.9.1/yaml.rb:391:in `emit'
/Users/.rvm/rubies/ruby-1.9.1-p378/lib/ruby/1.9.1/yaml.rb:391:in `quick_emit'
/Users/.rvm/rubies/ruby-1.9.1-p378/lib/ruby/1.9.1/yaml/rubytypes.rb:86:in `to_yaml'
vendor/plugins/delayed_job/lib/delayed/backend/base.rb:65:in `payload_object='
activerecord (2.3.9) lib/active_record/base.rb:2918:in `block in assign_attributes'
activerecord (2.3.9) lib/active_record/base.rb:2914:in `each'
activerecord (2.3.9) lib/active_record/base.rb:2914:in `assign_attributes'
activerecord (2.3.9) lib/active_record/base.rb:2787:in `attributes='
activerecord (2.3.9) lib/active_record/base.rb:2477:in `initialize'
activerecord (2.3.9) lib/active_record/base.rb:725:in `new'
activerecord (2.3.9) lib/active_record/base.rb:725:in `create'
vendor/plugins/delayed_job/lib/delayed/backend/base.rb:21:in `enqueue'

I would guess that it is caused by the fact that you send the objects as arguments to your jobs (at least I assume that current_user and object are in fact objects and not id's). Send the id's instead and start with loading the objects when perform starts.
For example:
Delayed::Job.enqueue(BackgroundProcess.new(current_user.id, object.id))
class BackgroundProcess < Struct.new(:user_id, :object_id)
def perform
#current_user = User.find(user_id)
#object = Object.find(object_id)
...
end
end
This way, it does not risk any problem with serializing an ActiveRecord into the database and you will always load the latest changes when the job is run.

Ran into this same problem as well. I still don't know what is causing it, but for some reason cloning the object seems to solve it
u = User.find 123
u.to_yaml
=> TypeError: wrong argument type nil (expected Data)
u.clone.to_yaml
=> works like normal
Very frustrating. Would be better to know the root cause, but this might help if you are desperate.

Related

o.respond_to?(:empty?) and o.empty? Fails with: "undefined method `empty?`"

so how is that possible?
I have a Module, that puts a Ruby Object at the end of the renderd page in a nice structured HTML. So i recurse through the given object and build the HTML output. The following is an excerpt of the code where the error is thrown.
EDIT:(had a copy error in code)
o=some object
nicer=if o.respond_to?(:empty?) and o.empty?
add_class='empty'
'empty ' + class_name
else
case o
when TrueClass then
"TRUE"
when FalseClass then
"FALSE"
when Array
#some more when's
the error thrown: undefined method 'empty?' for #Journey::Routes:0x123456
the object (o) it self is ActionDispatch::Routing::RouteSet
again: how is that possible?
EDIT: Stack: (there is the bad one ...)
actionpack (3.2.13) lib/action_dispatch/routing/route_set.rb:366:in `empty?'
lib/tech_draw.rb:90:in `format_nice'
lib/tech_draw.rb:101:in `block in format_nice'
lib/tech_draw.rb:100:in `each'
lib/tech_draw.rb:100:in `map'
lib/tech_draw.rb:100:in `format_nice'
lib/tech_draw.rb:124:in `block in format_nice'
lib/tech_draw.rb:123:in `map'
lib/tech_draw.rb:123:in `format_nice'
lib/tech_draw.rb:13:in `block in say'
lib/tech_draw.rb:13:in `map'
lib/tech_draw.rb:13:in `say'
lib/tech_draw.rb:13:in `map'
lib/tech_draw.rb:6:in `say'
app/controllers/home_controller.rb:131:in `any_page'
actionpack (3.2.13) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
...
How is that possible? Easy:
class Thing
def respond_to? *args
true
end
end
o = Thing.new
o.respond_to?(:empty?) and o.empty?
# => NoMethodError: undefined method `empty?' for #<Thing:0x00000100ae2558>
Although why is it happening in this case is another matter.
ActionDispatch::Routing::RouteSet#empty? appears to call empty? on routes object. Assuming this object is an instance of Journey::Routes that would explain the error, as Journey::Routes doesn’t have an empty? method. (In current Rails versions Journey is part of Rails itself, but in Rails 3.2 it is separate).
I don’t why this is happening in your case though.

Wrong number of arguments (0 for 1) in default scope

I keep getting the error ArgumentError: wrong number of arguments (0 for 1) for my default_scope which is default_scope { where("#{table_name}.tenant_id IS NULL") }
It keeps giving me this error and I don't understand why. I have the default scope in my users model.
Update:
Error output if using rails console:
ArgumentError: wrong number of arguments (0 for 1)
from /home/evan/Apps/demo-application/app/models/user.rb:18:in `hash'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/scoping.rb:64:in `value_for'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activesupport-4.0.4/lib/active_support/per_thread_registry.rb:40:in `public_send'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activesupport-4.0.4/lib/active_support/per_thread_registry.rb:40:in `block in method_missing'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/scoping/default.rb:123:in `ignore_default_scope?'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/scoping/default.rb:134:in `evaluate_default_scope'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/scoping/default.rb:110:in `build_default_scope'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/relation.rb:554:in `with_default_scope'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/relation.rb:582:in `exec_queries'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/relation.rb:471:in `load'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/relation.rb:220:in `to_a'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/relation.rb:573:in `inspect'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/railties-4.0.4/lib/rails/commands/console.rb:90:in `start'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/railties-4.0.4/lib/rails/commands/console.rb:9:in `start'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/railties-4.0.4/lib/rails/commands.rb:62:in `<top (required)>'
from bin/rails:4:in `require'
The hash is in my user model as below.
def User.new_remember_token
SecureRandom.urlsafe_base64
end
def User.hash(token)
Digest::SHA1.hexdigest(token.to_s)
end
private
def create_remember_token
self.remember_token = User.hash(User.new_remember_token)
end
Error output if using rails server:
ArgumentError - wrong number of arguments (0 for 1):
activerecord (4.0.4) lib/active_record/scoping.rb:70:in `set_value_for'
activesupport (4.0.4) lib/active_support/per_thread_registry.rb:40:in `block in method_missing'
activerecord (4.0.4) lib/active_record/scoping/default.rb:127:in `ignore_default_scope='
activerecord (4.0.4) lib/active_record/scoping/default.rb:140:in `ensure in evaluate_default_scope'
activerecord (4.0.4) lib/active_record/scoping/default.rb:140:in `evaluate_default_scope'
activerecord (4.0.4) lib/active_record/scoping/default.rb:110:in `build_default_scope'
activerecord (4.0.4) lib/active_record/relation.rb:554:in `with_default_scope'
activerecord (4.0.4) lib/active_record/relation.rb:582:in `exec_queries'
activerecord (4.0.4) lib/active_record/relation.rb:471:in `load'
activerecord (4.0.4) lib/active_record/relation.rb:220:in `to_a'
activerecord (4.0.4) lib/active_record/relation/finder_methods.rb:316:in `find_take'
activerecord (4.0.4) lib/active_record/relation/finder_methods.rb:66:in `take'
activerecord (4.0.4) lib/active_record/relation/finder_methods.rb:49:in `find_by'
activerecord (4.0.4) lib/active_record/querying.rb:6:in `find_by'
app/helpers/sessions_helper.rb:16:in `current_user'
app/helpers/sessions_helper.rb:19:in `signed_in?'
And the relevant rails methods:
def ignore_default_scope? # :nodoc:
ScopeRegistry.value_for(:ignore_default_scope, self)
end
def ignore_default_scope=(ignore) # :nodoc:
ScopeRegistry.set_value_for(:ignore_default_scope, self, ignore)
end
You should avoid overwriting Ruby core methods like Object#hash, also considering that Object#hash is an essential method in Ruby. From the docs:
Generates a Fixnum hash value for this object. This function must have
the property that a.eql?(b) implies a.hash == b.hash.
The hash value is used along with eql? by the Hash class to determine
if two objects reference the same hash key. Any hash value that
exceeds the capacity of a Fixnum will be truncated before being used.
The hash value for an object may not be identical across invocations
or implementations of ruby. If you need a stable identifier across
ruby invocations and implementations you will need to generate one
with a custom method.
If you really have to overwrite core methods you should guarantee their functionality and do not change their arguments: you will get unexpected behaviours all over your app otherwise, like the error you're referring.
I think that you have not such a variable or method as table_name
I think this will work:
table name = "users"
default_scope { where("#{table_name}.tenant_id IS NULL") }
Also it is cleaner to use callable objects for scopes (they are waiting for it), so it is better to use lambda here:
table name = "users"
default_scope ->{ where("#{table_name}.tenant_id IS NULL") }
# or old syntax:
default_scope lambda { where("#{table_name}.tenant_id IS NULL") }

Rails 3.2 Uniqueness validation raises undefined method 'zero?' for nil:Nilclass

I am using Rails 3.2.0.
I have a simple model as show below
class Favorite < ActiveRecord::Base
validates :lst, :presence => true
validates :uuid, :presence => true, :uniqueness => {:scope => :lst}
end
If I try this
f = Favorite.new
f.valid?
I get the following error message:
NoMethodError: undefined method `zero?' for nil:NilClass
from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.0/lib/active_record/associations/alias_tracker.rb:28:in `aliased_name_for'
from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.0/lib/active_record/associations/join_dependency.rb:17:in `initialize'
from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.0/lib/active_record/relation/finder_methods.rb:219:in `new'
from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.0/lib/active_record/relation/finder_methods.rb:219:in `construct_join_dependency_for_association_find'
from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.0/lib/active_record/relation/finder_methods.rb:192:in `exists?'
from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.0/lib/active_record/validations/uniqueness.rb:32:in `validate_each'
from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.0/lib/active_model/validator.rb:153:in `block in validate'
from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.0/lib/active_model/validator.rb:150:in `each'
from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.0/lib/active_model/validator.rb:150:in `validate'
from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.2.0/lib/active_support/callbacks.rb:310:in `_callback_before_15'
from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.2.0/lib/active_support/callbacks.rb:429:in `_run__1275595979440079611__validate__42615372200132002__callbacks'
from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.2.0/lib/active_support/callbacks.rb:405:in `__run_callback'
from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.2.0/lib/active_support/callbacks.rb:385:in `_run_validate_callbacks'
from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.2.0/lib/active_support/callbacks.rb:81:in `run_callbacks'
from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.0/lib/active_model/validations.rb:212:in `run_validations!'
from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.0/lib/active_model/validations/callbacks.rb:53:in `block in run_validations!'
....
....
ActiveRecord AREL table aliasing is breaking
The error is likely due to ActiveRecord AREL losing track of how to sum an empty array.
The relevant line of code is in the file alias_tracker.rb:
count.sum
If count is an empty array then the line evaluates as:
[].sum
In Ruby that fails:
$ irb
> [].sum
NoMethodError: undefined method `sum' for []:Array
Rails ActiveSupport Enumerable#sum
In Rails that succeeds because ActiveSupport is creating Enumerable#sum
$ irb
> require 'active_support/core_ext/enumerable'
> [].sum
=> 0
Your problem is likely that some unrelated area of your app is also creating Enumerable#sum or Array#sum. The unrelated code is overwriting the Rails method.
The could be happening in your code or in an unrelated gem. The Rails gem loads early, typically first in your Gemfile, and any later gem can interfere with Rails.
How to fix it?
Have you written a method named sum, perhaps within a module named Enumerable or Array? If so, that's a good place to start. You could rename your method, or you could try changing your method to match the Rails method by replacing your #sum code with this code:
module Enumerable
def sum(identity = 0, &block)
if block_given?
map(&block).sum(identity)
else
inject(:+) || identity
end
end
end
If you haven't written a method named sum in your code, then the conflict is likely in a gem you're using. Try commenting-out gems that you're using then reload your app.
You can search for a gem that defines a method named sum like this:
$ cd /usr/lib/ruby/gems
$ find | xargs grep "def sum\b"
Are you using any gems named sixarm? If so, contact me and I'll fix them for you. These are by me, and a few of them do define #sum for use with statistics tools and utilties.
Hope this helps. Can you post here if it solves your issue?

JSON.dump on any ActiveRecord object fails

I've got a project running Rails 3.1.3 and JSON gem 1.6.3, and am unable to pass any ActiveRecord instance to JSON.dump. I always get the following error:
NoMethodError: undefined method `[]=' for #<JSON::Ext::Generator::State:0x000001033f2088>
from /Users/andy/.rvm/gems/ruby-1.9.2-p180#project/gems/activerecord-3.1.3/lib/active_record/serialization.rb:10:in `serializable_hash'
from /Users/andy/.rvm/gems/ruby-1.9.2-p180#project/gems/activemodel-3.1.3/lib/active_model/serializers/json.rb:84:in `as_json'
from /Users/andy/.rvm/gems/ruby-1.9.2-p180#project/gems/activesupport-3.1.3/lib/active_support/json/encoding.rb:47:in `block in encode'
from /Users/andy/.rvm/gems/ruby-1.9.2-p180#project/gems/activesupport-3.1.3/lib/active_support/json/encoding.rb:78:in `check_for_circular_references'
from /Users/andy/.rvm/gems/ruby-1.9.2-p180#project/gems/activesupport-3.1.3/lib/active_support/json/encoding.rb:46:in `encode'
from /Users/andy/.rvm/gems/ruby-1.9.2-p180#project/gems/activesupport-3.1.3/lib/active_support/json/encoding.rb:31:in `encode'
from /Users/andy/.rvm/gems/ruby-1.9.2-p180#project/gems/activesupport-3.1.3/lib/active_support/core_ext/object/to_json.rb:20:in `to_json'
from /Users/andy/.rvm/gems/ruby-1.9.2-p180#project/gems/json-1.6.3/lib/json/common.rb:216:in `generate'
from /Users/andy/.rvm/gems/ruby-1.9.2-p180#project/gems/json-1.6.3/lib/json/common.rb:216:in `generate'
from /Users/andy/.rvm/gems/ruby-1.9.2-p180#project/gems/json-1.6.3/lib/json/common.rb:380:in `dump'
Passing JSON.dump a hash, an instance of a non-ActiveRecord class, etc. work fine, and #to_json works on my ActiveRecord instances. I can't just call #to_json instead, though, as it is actually a library I'm passing my ActiveRecord object to that calls JSON.dump. However I have the same problem skipping that other library altogether and just calling JSON.dump myself.
Any help is much appreciated!
Based on the links below, it sounds like there's an issue with JSON overriding to_json with its own encoding.
https://rails.lighthouseapp.com/projects/8994/tickets/4925-rails-3-to_json-incompatible-with-json-core-library
https://rails.lighthouseapp.com/projects/8994/tickets/4494-ruby-192-heads-json-support-breaks-to_json-for-arrays-of-records
https://github.com/defunkt/resque/issues/149
The workaround that popped up in the threads a few times was to put the following code into your environments.rb file.
class Array
def to_json(*a)
ActiveSupport::JSON.encode(self)
end
end

activerecord-2.3.14 breaks with ruby 1.9.2 ::undefined method `reject' for "4":String

undefined method `reject' for "4":String
is thrown when I try to perform #user.update_attributes(params).
The params list is as follows
"user"=>{"login"=>"admin", "first_name"=>"Admin", "last_name"=>"Admin", "email"=>"nfsurveytest+admin#neurofocus.com", "location_id"=>"1", "last_login_at_text"=>"Never logged in", "password"=>"", "password_confirmation"=>"", "role_ids"=>"4", "active"=>"true", "is_staff"=>"true"},
The error stack is as below
/home/narendra/.rvm/gems/ruby-1.9.2-p290#nf_schedule/gems/activerecord-2.3.14 /lib/active_record/associations.rb:1336:in block in collection_accessor_methods'
/home/narendra/.rvm/gems/ruby-1.9.2-p290#nf_schedule/gems/activerecord-2.3.14/lib/active_record/base.rb:2918:inblock in assign_attributes'
/home/narendra/.rvm/gems/ruby-1.9.2-p290#nf_schedule/gems/activerecord-2.3.14/lib/active_record/base.rb:2914:in each'
/home/narendra/.rvm/gems/ruby-1.9.2-p290#nf_schedule/gems/activerecord-2.3.14/lib/active_record/base.rb:2914:inassign_attributes'
/home/narendra/.rvm/gems/ruby-1.9.2-p290#nf_schedule/gems/activerecord-2.3.14/li b/active_record/base.rb:2787:in attributes='
/home/narendra/.rvm/gems/ruby-1.9.2-p290#nf_schedule/gems/activerecord-2.3.14/lib/active_record/base.rb:2671:inupdate_attributes_inside_transaction'
/home/narendra/.rvm/gems/ruby-1.9.2-p290#nf_schedule/gems/activerecord-2.3.14/lib/active_record/transactions.rb:229:in block in with_transaction_returning_status'
/home/narendra/.rvm/gems/ruby-1.9.2-p290#nf_schedule/gems/activerecord-2.3.14/lib/active_record/connection_adapters/abstract/database_statements.rb:136:intransaction'
/home/narendra/.rvm/gems/ruby-1.9.2-p290#nf_schedule/gems/activerecord-2.3.14/lib/active_record/transactions.rb:182:in transaction'
/home/narendra/.rvm/gems/ruby-1.9.2-p290#nf_schedule/gems/activerecord-2.3.14/lib/active_record/transactions.rb:228:inwith_transaction_returning_status'
/home/narendra/.rvm/gems/ruby-1.9.2-p290#nf_schedule/gems/activerecord-2.3.14/lib/active_record/base.rb:2667:in update_attributes'
/home/narendra/workspace/nf_schedule/app/controllers/users_controller.rb:100:inupdate'
I assume this breaks as String in ruby 1.9.2 does not mixin 'Enumerable'.
Can anyone confirm if this is an issue or I am missing something?
https://github.com/rails/rails/issues/3434
You're supplying a String where ActiveRecord is expecting an Array. You could remap the offending parameter in the controller using something like this:
if (params[:user])
params[:user][:role_ids] = [ params[:user][:role_ids] ]
end
You could also adjust your form so that the field is named role_ids[] instead of just role_ids so that it will be submitted as an array.

Resources