Problem calling global methods(?) #416

Closed
joliss opened this Issue Jul 26, 2012 · 3 comments

Comments

Projects
None yet
2 participants
@joliss

joliss commented Jul 26, 2012

To get FG working with Spork, I added require: false in Gemfile and put

Spork.each_run do
  require 'factory_girl_rails'
end

So far so good. But now that FG is getting loaded later, the following does not work any more:

FactoryGirl.define do
  factory :foo do
    count Forgery(:basic).number
  end
end

It throws

/.../factories/foo.rb:3:in `block (2 levels) in <top (required)>': undefined method `number' for #<FactoryGirl::Declaration::Static:0x00000004687f00> (NoMethodError)

Apparently Forgery is a method and is overloaded as a class.

But the following works fine:

FactoryGirl.define do
  factory :foo do
    count Forgery::Basic.number
  end
end

So I have a workaround, and I know I'm not supposed to use Forgery with FG.

That said, I know there is some magic going on in factory definitions, and I'd be curious, is there anything going wrong that stops global methods from being called? Can I fix it somehow?

@joshuaclayton

This comment has been minimized.

Show comment Hide comment
@joshuaclayton

joshuaclayton Jul 26, 2012

Member

Assuming Forgery (the method) is defined on object, I think you could do: Object.Forgery(:whatever).

That said, you should just be able to pass count a block and both should work:

FactoryGirl.define do
  factory :installment_billing do
    count { Forgery(:basic).number }
  end
end

Any reason for not just assigning it explicitly?

Member

joshuaclayton commented Jul 26, 2012

Assuming Forgery (the method) is defined on object, I think you could do: Object.Forgery(:whatever).

That said, you should just be able to pass count a block and both should work:

FactoryGirl.define do
  factory :installment_billing do
    count { Forgery(:basic).number }
  end
end

Any reason for not just assigning it explicitly?

@joliss

This comment has been minimized.

Show comment Hide comment
@joliss

joliss Jul 26, 2012

Hey, thanks for the quick reply!

The block thing crashes with the same (IIRC) "undefined method" error as above, though at run-time, not at load-time.

Object.Forgery doesn't work either, it says private method called.

[3] pry(main)> method :Forgery
=> #<Method: Object#Forgery>
[4] pry(main)> Forgery
=> Forgery
[6] pry(main)> Object.Forgery
NoMethodError: private method `Forgery' called for Object:Class
from (pry):6:in `<main>'
[5] pry(main)> Object.new.Forgery
NoMethodError: private method `Forgery' called for #<Object:0x00000005246918>
from (pry):5:in `<main>'

Any reason for not just assigning it explicitly?

Yes, I just ended up yanking all the forgery calls from the factories, as they had to go anyway. The reason I posted this is more that I'm worried that something's fundamentally going wrong with the delayed loading, since it worked fine before (without require: false). Any ideas at all?

joliss commented Jul 26, 2012

Hey, thanks for the quick reply!

The block thing crashes with the same (IIRC) "undefined method" error as above, though at run-time, not at load-time.

Object.Forgery doesn't work either, it says private method called.

[3] pry(main)> method :Forgery
=> #<Method: Object#Forgery>
[4] pry(main)> Forgery
=> Forgery
[6] pry(main)> Object.Forgery
NoMethodError: private method `Forgery' called for Object:Class
from (pry):6:in `<main>'
[5] pry(main)> Object.new.Forgery
NoMethodError: private method `Forgery' called for #<Object:0x00000005246918>
from (pry):5:in `<main>'

Any reason for not just assigning it explicitly?

Yes, I just ended up yanking all the forgery calls from the factories, as they had to go anyway. The reason I posted this is more that I'm worried that something's fundamentally going wrong with the delayed loading, since it worked fine before (without require: false). Any ideas at all?

@joshuaclayton

This comment has been minimized.

Show comment Hide comment
@joshuaclayton

joshuaclayton Jul 27, 2012

Member

@joliss nothing jumps out at me, to be honest. In FactoryGirl::DefinitionProxy (the class that handles processing of all the attributes as they're declared in a factory :whatever block), we undefine a bunch of methods in order to avoid having attribute names collide with methods on Object and Kernel. This tends to cause the most surprises, so it's weird that require: false would be doing so much. I'm going to close the ticket for now, since you're not using Forgery anymore, but reopen it if you're dead set on using it again and want to try to get it working!

Member

joshuaclayton commented Jul 27, 2012

@joliss nothing jumps out at me, to be honest. In FactoryGirl::DefinitionProxy (the class that handles processing of all the attributes as they're declared in a factory :whatever block), we undefine a bunch of methods in order to avoid having attribute names collide with methods on Object and Kernel. This tends to cause the most surprises, so it's weird that require: false would be doing so much. I'm going to close the ticket for now, since you're not using Forgery anymore, but reopen it if you're dead set on using it again and want to try to get it working!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment