I'm trying to make my tests robust and really solid, and I've been breaking down some complex queries and associations into smaller ones, or refactoring and moving the data into scopes.
Given the following classes:
class Item < ActiveRecord::Base
belongs_to :location
scope :in_location, ->(location) { where(location: location) }
scope :findable, ->(location, not_ids) {
in_location(location).where.not(id: not_ids)
}
end
class Container < ActiveRecord::Base
belongs_to :location
# THIS IS WHAT I WANT TO TEST
has_many :findable_items, ->(container) {
findable(container.location, container.not_findable_ids)
}, class_name: 'Item'
end
How would you test a variable has_many relationship like this without hitting the database to a significant degree? I know I can test the Item.findable method on it's own; what I'm interested in is the container.findable_items method.
Note: the actual association being tested is more complex than this, and would require pretty extensive set-up; it's running through a few other nested associations and scopes. I'd like to avoid this setup if possible, and just test that the scope is called with the correct values.
Relevant parts of my Gemfile:
rails (4.2.3)
shoulda-matchers (2.6.2)
factory_girl (4.5.0)
factory_girl_rails (4.5.0)
rspec-core (3.3.2)
rspec-expectations (3.3.1)
rspec-its (1.2.0)
rspec-mocks (3.3.2)
rspec-rails (3.3.3)
I have shoulda-matchers in my project, so I can do the basic sanity test:
it { should have_many(:findable_items).class_name('Item') }
but this fails:
describe 'findable_line_items' do
let(:container) { #container } # where container is a valid but unsaved Container
let(:location) { #container.location }
it 'gets items that are in the location and not excluded' do
container.not_findable_ids = [1,2]
# so it doesn't hit the database
expect(Item).to receive(:findable).with(location, container.not_findable_ids)
container.findable_items
end
end
This spec fails with the following error:
1) Container findable_line_items gets items that are in the location and not excluded
Failure/Error: container.findable_items
NoMethodError:
undefined method `except' for nil:NilClass
# /[redacted]/gems/activerecord-4.2.3/lib/active_record/associations/association_scope.rb:158:in `block (2 levels) in add_constraints'
# /[redacted]/gems/activerecord-4.2.3/lib/active_record/associations/association_scope.rb:154:in `each'
# /[redacted]/gems/activerecord-4.2.3/lib/active_record/associations/association_scope.rb:154:in `block in add_constraints'
# /[redacted]/gems/activerecord-4.2.3/lib/active_record/associations/association_scope.rb:141:in `each'
# /[redacted]/gems/activerecord-4.2.3/lib/active_record/associations/association_scope.rb:141:in `each_with_index'
# /[redacted]/activerecord-4.2.3/lib/active_record/associations/association_scope.rb:141:in `add_constraints'
# /[redacted]/activerecord-4.2.3/lib/active_record/associations/association_scope.rb:39:in `scope'
# /[redacted]/gems/activerecord-4.2.3/lib/active_record/associations/association_scope.rb:5:in `scope'
# /[redacted]/gems/activerecord-4.2.3/lib/active_record/associations/association.rb:97:in `association_scope'
# /[redacted]/gems/activerecord-4.2.3/lib/active_record/associations/association.rb:86:in `scope'
# /[redacted]/gems/activerecord-4.2.3/lib/active_record/associations/collection_association.rb:423:in `scope'
# /[redacted]/gems/activerecord-4.2.3/lib/active_record/associations/collection_proxy.rb:37:in `initialize'
# /[redacted]/gems/activerecord-4.2.3/lib/active_record/relation/delegation.rb:106:in `new'
# /[redacted]/gems/activerecord-4.2.3/lib/active_record/relation/delegation.rb:106:in `create'
# /[redacted]/gems/activerecord-4.2.3/lib/active_record/associations/collection_association.rb:39:in `reader'
# /[redacted]/gems/activerecord-4.2.3/lib/active_record/associations/builder/association.rb:115:in `pickable_items'
# ./spec/models/container_spec.rb:25:in `block (3 levels) in <top (required)>'
How would you get this spec to pass, without actually setting up an Item that meets all the requirements?
I ended up going with a solution like this:
describe 'findable_line_items' do
let(:container) { #container } # where container is a valid but unsaved Container
let(:location) { #container.location }
it 'gets items that are in the location and not excluded' do
# so it doesn't hit the database
expect(Item).to receive(:findable).with(location, container.not_findable_ids).and_call_original
expect(container).to receive(:location).and_call_original
expect(container).to receive(:not_findable_ids).and_call_original
container.findable_items
end
end
The error that was occurring was somewhere in the ActiveRecord association setup; it was trying to instantiate an ActiveRecord array on a nil object which was being returned from my Item stub. Adding .and_call_original solved that error.
I don't really care to test that the correct objects are being returned from this association, since that scope is being tested elsewhere, just that the scope is being used. It still hits the database in this scenario, but not the 15 times that would be required to set up a full test.
Related
Is it just me or is it a global RSpec behavior that when I name my rails model scope :public, initialize object from this model, and stub this object Rspec fails
class DocumentName < ActiveRecord::Base
scope :public, lambda{where( public: true) } #line 3
end
nothing special, Rails application works
DocumentName.public # => [ #DN, #DN, #DN... ]
# SELECT `document_names`.* FROM `document_names` WHERE `document_names`.`public` = 1
however RSpec fails
describe DocumentName do
let(:resource){DocumentName.new}
it do
resource.stub(:name).and_return('foo') #line 16
resource.save.should be true
end
end
Failure/Error: resource.stub(:name).and_return('foo')
ArgumentError:
wrong number of arguments (1 for 0)
# ./app/models/document_name.rb:3:in `block in <class:DocumentName>'
# ./spec/models/document_name_spec.rb:16:in `block (2 levels) in <top (required)>'
...and funniest thing, I'm not doing anything with that scope in this scenario.
However if I name this scope something else than :public e.g: :are_public:
class DocumentName < ActiveRecord::Base
scope :are_public, lambda{where( public: true) }
end
...everything pass O_O
Rails 3.2.11 (but same thing on any 3.2.x)
Ruby ruby-2.0.0-rc1 ( but same for any ruby-1.9.3)
rspec-core (2.12.2)
rspec-expectations (2.12.1)
rspec-mocks (2.12.1)
rspec-rails (2.12.2)
private and public are Ruby's access modifiers:
class User
private
def some_private_method
end
public
def some_public_method
end
end
While they may seem like keywords, they are actually method calls. It's not really a good idea to overwrite them.
I have an Active Record model object called Event, which has many event_things. I want to be able to duplicate the event, so that it gets a new id. I'm using Rails 3.2 and in rails console am able to successfully call
event_copy = event.dup
event_copy.save
However, I also want to duplicate each of the Event's event_things.
copy = event_thing.dup
copy.event_id = event_copy.id
copy.save
But that gives me this error stack:
NoMethodError: undefined method `yaml' for nil:NilClass
from /Users/Ed/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/psych.rb:204:in `dump_stream'
from /Users/Ed/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/psych/core_ext.rb:35:in `psych_y'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:143:in `attribute_change'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:117:in `block in changes'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:117:in `map'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:117:in `changes'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/attribute_methods/dirty.rb:23:in `save'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:241:in `block (2 levels) in save'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:295:in `block in with_transaction_returning_status'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:208:in `transaction'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:293:in `with_transaction_returning_status'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:241:in `block in save'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:252:in `rollback_active_record_state!'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:240:in `save'
from (irb):18
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.6/lib/rails/commands/console.rb:47:in `start'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.6/lib/rails/commands/console.rb:8:in `start'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.6/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
I ran into the same issue as this. It turns out that there's a Kernel.y extension method that is getting in your way, based on this article. Here is what I did to fix my problem:
class Event < ActiveRecord::Base
# alias the attributes
alias_attribute :x_pos, :x
alias_attribute :y_pos, :y
after_initialize :init
# after_initialize will still work, with the aliases
def init
self.x_pos ||= 0
self.y_pos ||= 0
end
# override Kernel.y
def y; end
# override self.y_pos to read out of the :attributes, since we blew away :y
def y_pos
attribute['y']
end
end
After doing this, I was finally able to use my model without having to rename the y database column.
While I normally don't advocate using gems liberally, if you have a lot of relations that need to be preserved in the duplication, or find yourself doing these manual duplications a lot, take a look at deep_clonable.
As for your specific error, try surrounding each line of code with a nil check (one line at a time). I'm sure there's just some case where you're ending up with a nil object that you're overlooking.
When running unit tests I get the following error for some of my tests:
6) Error:
test_name_can't_be_nil(NodeTest):
NoMethodError: undefined method `detect' for :"Node#children":Symbol
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/naming.rb:85:in `model_name'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/errors.rb:315:in `generate_message'
org/jruby/RubyArray.java:2339:in `collect'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/errors.rb:314:in `generate_message'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/errors.rb:235:in `add'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/errors.rb:256:in `add_on_blank'
org/jruby/RubyArray.java:1615:in `each'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/errors.rb:254:in `add_on_blank'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/validations/presence.rb:9:in `validate'
org/jruby/RubyBasicObject.java:1704:in `__send__'
org/jruby/RubyKernel.java:2101:in `send'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activesupport-3.1.4/lib/active_support/callbacks.rb:306:in `_callback_before_47'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activesupport-3.1.4/lib/active_support/callbacks.rb:410:in `_run_validate_callbacks'
org/jruby/RubyBasicObject.java:1698:in `__send__'
org/jruby/RubyKernel.java:2097:in `send'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activesupport-3.1.4/lib/active_support/callbacks.rb:81:in `run_callbacks'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/validations.rb:212:in `run_validations!'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/validations.rb:179:in `valid?'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/neo4j-2.0.1-java/lib/neo4j/rails/validations.rb:29:in `valid?'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/neo4j-2.0.1-java/lib/neo4j/rails/callbacks.rb:26:in `valid_with_callbacks?'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activesupport-3.1.4/lib/active_support/callbacks.rb:405:in `_run_validation_callbacks'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/neo4j-2.0.1-java/lib/neo4j/rails/callbacks.rb:26:in `valid_with_callbacks?'
/Users/dave/Projects/myapp/test/test_helper.rb:11:in `assert_presence'
/Users/dave/Projects/myapp/test/unit/node_test.rb:9:in `test_name_can't_be_nil'
org/jruby/RubyBasicObject.java:1698:in `__send__'
The offending test in question is:
class NodeTest < ActiveSupport::TestCase
def assert_presence( model, field)
model.send( (field.to_s + '='), nil )
model.valid?
assert_match /can not be blank/, model.errors[field].join,
"Presence error for #{field} not found on #model.class"
end
def setup
#node = FactoryGirl.build :node
end
test "name can't be nil" do
assert_presence #node, :name
end
....
end
Where Nodes are defined in the model as:
class Node < Neo4j::Rails::Model
include Neo4j::NodeMixin
property :name, type: String, index: :exact
property :description, type: String
has_one(:creator).from(User, :created_nodes)
has_n(:children).to(Node) ## <--- Suspected difficult line
has_n(:parents).from(Node, :children) ## <--- Suspected difficult line
has_n(:capable_users).from(User, :capabilities)
# The following has the Class commented out because this somehow triggers
# an error from the 'has_n(:children).to(Node)' line
has_n(:challenges) #.to(Challenge)
....
end
Basically, the server can run fine, but will crash anytime I try to call valid? on a Node (not other models). Does anyone know why this might be happening?
The problem was my choice of attributes, namely parents (and maybe children).
I took a look at the source in active model where the error was occurring (here), and saw this:
def model_name
#_model_name ||= begin
namespace = self.parents.detect { |n| n.respond_to?(:_railtie) } # <--- this line
ActiveModel::Name.new(self, namespace)
end
end
As you can see, parents appears to be in use. I changed the names and the validations, saving, etc, now works.
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?
The bug is many months old, here:
http://www.ruby-forum.com/topic/1094002
Two links in that which show code changes:
https://github.com/godfat/ruby/commit/f4e0e8f781b05c767ad2472a43a4ed0727a75708
https://github.com/godfat/ruby/commit/c7a6cf975d88828c2ed27d253f41c480f9b66ad6
I have Ruby 1.9.2 and rvm. I would have pasted those changes into the appropriate files, but I don't know how.
This worked a few days ago. I can't do Ruby on Rails commands like:
>> User.create :username => "a", :password => "a"
Here is the error message:
ArgumentError: wrong number of arguments(1 for 0)
from /Users/RedApple/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:48:in `method'
from /Users/RedApple/.rvm/rubies/ruby-1.9.2 p290/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:48:in `accept'
from /Users/RedApple/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:36:in `<<'
from /Users/RedApple/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/psych.rb:165:in `dump'
from /Users/RedApple/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/psych/core_ext.rb:13:in `psych_to_yaml'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.0.4/lib/delayed/backend/base.rb:57:in `payload_object='
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2918:in `block in assign_attributes'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2914:in `each'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2914:in `assign_attributes'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2787:in `attributes='
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2477:in `initialize'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:725:in `new'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:725:in `create'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.0.4/lib/delayed/message_sending.rb:9:in `method_missing'
from /Users/RedApple/S/app/models/user.rb:29:in `block in <class:User>'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-2.3.14/lib/active_support/callbacks.rb:182:in `call'
... 7 levels...
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/callbacks.rb:267:in `create_with_callbacks'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2927:in `create_or_update'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/callbacks.rb:250:in `create_or_update_with_callbacks'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2577:in `save'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/validations.rb:1089:in `save_with_validation'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/dirty.rb:79:in `save_with_dirty'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:229:in `block in with_transaction_returning_status'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:182:in `transaction'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:228:in `with_transaction_returning_status'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:196:in `block in save_with_transactions'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:208:in `rollback_active_record_state!'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:196:in `save_with_transactions'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:727:in `create'
from (irb):1
from /Users/RedApple/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16:in `<main>'>
Line 28-30 in user.rb:
after_create do |user|
user.delay( :priority => -15 ).seed
end
I am dead in the water without this. Can anyone help?
Delayed Job and the Ruby 1.9.2 YAML parser (Psych) are unfortunately not compatible.
Switch back to the previous YAML parser (Syck) by adding this to your config/application.rb, just below the call to Bundler.require:
YAML::ENGINE.yamler = "syck" if RUBY_VERSION >= "1.9.2"
You could patch your Ruby, but it's not easy and not really possible on managed hosts.
My solution was to create a monkeypatch based on the patch commit 31075.
Create an initializer file in your Rails project
config/initializers/psych_extensions.rb
and add this code:
# APPLIES RUBY PATCH REVISION 31075
module Psych
module Visitors
###
# YAMLTree builds a YAML ast given a ruby object. For example:
#
# builder = Psych::Visitors::YAMLTree.new
# builder << { :foo => 'bar' }
# builder.tree # => #<Psych::Nodes::Stream .. }
#
class YAMLTree < Psych::Visitors::Visitor
def accept target
# return any aliases we find
if node = #st[target.object_id]
node.anchor = target.object_id.to_s
return #emitter.alias target.object_id.to_s
end
if target.respond_to?(:to_yaml)
loc = target.public_method(:to_yaml).source_location.first
if loc !~ /(syck\/rubytypes.rb|psych\/core_ext.rb)/
unless target.respond_to?(:encode_with)
if $VERBOSE
warn "implementing to_yaml is deprecated, please implement \"encode_with\""
end
target.to_yaml(:nodump => true)
end
end
end
if target.respond_to?(:encode_with)
dump_coder target
else
send(#dispatch_cache[target.class], target)
end
end
private
# FIXME: remove this method once "to_yaml_properties" is removed
def find_ivars target
loc = target.public_method(:to_yaml_properties).source_location.first
unless loc.start_with?(Psych::DEPRECATED) || loc.end_with?('rubytypes.rb')
if $VERBOSE
warn "#{loc}: to_yaml_properties is deprecated, please implement \"encode_with(coder)\""
end
return target.to_yaml_properties
end
target.instance_variables
end
end
end
end