Skip to content
This repository

undefined method times for #<FactoryGirl::Declaration::Static (NoMethodError) #229

Closed
radosch opened this Issue November 04, 2011 · 12 comments

3 participants

Rafael Dalmacio Schaer Joshua Clayton Joe Ferris
Rafael Dalmacio Schaer

f.sequence(:tag_list) { rand(1..5).times.map{ tags[rand(tags.size)]}.join(", ") }

somehow, you cannot eval methods.
works not anymore, any idea?

Joshua Clayton

Depending on your version of Ruby, you'll want to use Kernel.rand or Random.rand instead.

Joshua Clayton joshuaclayton closed this November 05, 2011
Rafael Dalmacio Schaer
Joshua Clayton

when you use 5.times.map, what error do you see? Also, rand(1..5) doesn't even work (it results in a TypeError). Please paste the full backtrace as well as the actual sequence you're using.

Rafael Dalmacio Schaer

hi joshua,

thnx for taking care of this! Here a few more infos...

sequence:

tags = %w(tag1 tag2 tag3 tag4 tag6 tag9 tag10)
clue_types = Clue.const_get("TYPES_#{I18n.locale.to_s}")

FactoryGirl.define do
  factory :clue do |f|
    f.sequence(:title){ |n| "A random title set here, with a random number like: #{n}"}
    f.sequence(:description){ Faker::Lorem.sentence(10)}
    f.clue_type{clue_types.values[rand(clue_types.size)].to_s}
    f.sequence(:tag_list) { rand(1..5).times.map{ tags[rand(tags.size)]}.join(", ") }
    f.sequence(:user_id) { User.all.map(&:id).shuffle.first }
    f.sequence(:visibility_mask) { (1..4).to_a.shuffle.first }
  end
end

Here is the full backtrace

  NoMethodError: undefined method `times' for #<FactoryGirl::Declaration::Static:0x0000012cdcbc98>
  /Users/rafael/Sites/testing.com/testing/spec/factories/clue.rb:9:in `block (3 levels) in <top (required)>'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/factory_girl-2.2.0/lib/factory_girl/sequence.rb:18:in `call'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/factory_girl-2.2.0/lib/factory_girl/sequence.rb:18:in `next'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/factory_girl-2.2.0/lib/factory_girl/definition_proxy.rb:111:in `block in sequence'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/factory_girl-2.2.0/lib/factory_girl/attribute/dynamic.rb:10:in `instance_exec'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/factory_girl-2.2.0/lib/factory_girl/attribute/dynamic.rb:10:in `add_to'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/factory_girl-2.2.0/lib/factory_girl/factory.rb:61:in `block in run'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/factory_girl-2.2.0/lib/factory_girl/attribute_list.rb:32:in `each'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/factory_girl-2.2.0/lib/factory_girl/attribute_list.rb:32:in `each'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/factory_girl-2.2.0/lib/factory_girl/factory.rb:58:in `run'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/factory_girl-2.2.0/lib/factory_girl/syntax/methods.rb:60:in `create'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/factory_girl-2.2.0/lib/factory_girl/syntax/vintage.rb:50:in `default_strategy'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/factory_girl-2.2.0/lib/factory_girl/syntax/vintage.rb:143:in `Factory'
  /Users/rafael/Sites/testing.com/testing/features/step_definitions/clue_steps.rb.rb:2:in `block in <top (required)>'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/core_ext/instance_exec.rb:48:in `instance_exec'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/core_ext/instance_exec.rb:48:in `block in cucumber_instance_exec'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/core_ext/instance_exec.rb:69:in `cucumber_run_with_backtrace_filtering'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/core_ext/instance_exec.rb:36:in `cucumber_instance_exec'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/rb_support/rb_step_definition.rb:62:in `invoke'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/step_match.rb:25:in `invoke'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/step_invocation.rb:59:in `invoke'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/step_invocation.rb:38:in `accept'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/tree_walker.rb:99:in `block in visit_step'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/tree_walker.rb:163:in `broadcast'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/tree_walker.rb:98:in `visit_step'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/step_collection.rb:15:in `block in accept'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/step_collection.rb:14:in `each'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/step_collection.rb:14:in `accept'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/tree_walker.rb:93:in `block in visit_steps'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/tree_walker.rb:163:in `broadcast'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/tree_walker.rb:92:in `visit_steps'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/scenario.rb:55:in `block (2 levels) in accept'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/runtime.rb:79:in `block (2 levels) in with_hooks'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/runtime.rb:95:in `before_and_after'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/runtime.rb:78:in `block in with_hooks'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/runtime/support_code.rb:120:in `call'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/runtime/support_code.rb:120:in `block (3 levels) in around'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/language_support/language_methods.rb:13:in `block in around'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/language_support/language_methods.rb:95:in `call'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/language_support/language_methods.rb:95:in `execute_around'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/language_support/language_methods.rb:12:in `around'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/runtime/support_code.rb:119:in `block (2 levels) in around'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/runtime/support_code.rb:117:in `call'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/runtime/support_code.rb:117:in `around'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/runtime.rb:90:in `around'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/runtime.rb:77:in `with_hooks'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/scenario.rb:53:in `block in accept'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/scenario.rb:108:in `with_visitor'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/scenario.rb:47:in `accept'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/tree_walker.rb:51:in `block in visit_feature_element'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/tree_walker.rb:163:in `broadcast'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/tree_walker.rb:50:in `visit_feature_element'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/feature.rb:43:in `block in accept'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/feature.rb:42:in `each'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/feature.rb:42:in `accept'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/tree_walker.rb:20:in `block in visit_feature'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/tree_walker.rb:163:in `broadcast'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/tree_walker.rb:19:in `visit_feature'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/features.rb:29:in `block in accept'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/features.rb:17:in `each'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/features.rb:17:in `each'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/features.rb:28:in `accept'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/tree_walker.rb:14:in `block in visit_features'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/tree_walker.rb:163:in `broadcast'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/ast/tree_walker.rb:13:in `visit_features'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/runtime.rb:45:in `run!'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/cli/main.rb:43:in `execute!'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/lib/cucumber/cli/main.rb:20:in `execute'
  /Users/rafael/.rvm/gems/ruby-1.9.2-p290@testing/gems/cucumber-1.1.1/bin/cucumber:14:in `<top (required)>'
  /Users/rafael/Sites/testing.com/testing/script/cucumber:9:in `load'
  /Users/rafael/Sites/testing.com/testing/script/cucumber:9:in `<top (required)>'
  -e:1:in `load'
  -e:1:in `<main>'
Joe Ferris
Owner
Rafael Dalmacio Schaer
This is not the problem. "times" can not be invoked in the Factory define block.
I think, there will be other methods too.


FactoryGirl.define do
  factory :clue do |f|
    f.sequence(:title){ |n| "Example Title #{n}"}
    f.sequence(:description){ Faker::Lorem.sentence(10)}
    f.clue_type{clue_types.values[rand(clue_types.size)].to_s}
    f.sequence(:tag_list) { 3.times.map{ tags[rand(tags.size)]}.join(", ") }
    f.sequence(:user_id) { User.all.map(&:id).shuffle.first }
    f.sequence(:visibility_mask) { (1..4).to_a.shuffle.first }
  end
end


TypeError: can't convert FactoryGirl::Declaration::Static into Integer
~/clueapp/spec/factories/clue.rb:9:in `[]'
~/clueapp/spec/factories/clue.rb:9:in `block (4 levels) in <top (required)>'
~/clueapp/spec/factories/clue.rb:9:in `times'
~/clueapp/spec/factories/clue.rb:9:in `each'
~/clueapp/spec/factories/clue.rb:9:in `map'
~/clueapp/spec/factories/clue.rb:9:in `block (3 levels) in <top (required)>'

Joshua Clayton

times absolutely positively can be executed in the block. I even created a spec in the FG test suite to ensure it works.

  it "works with times and rand" do
    FactoryGirl.define do
      sequence(:letters) { 3.times.map { rand(5) } }
    end

    p generate(:letters)
  end

This test prints out [2, 3, 1], then [4, 4, 1], then [4, 1, 2]... etc. rand works (even without being called on Kernel or Random), as does times. So, now that we know those work, let's move on to figure out what the real issue is.

It looks like what you're seeing here with [] is accessing tags, which I remember you mentioning in a comment earlier. You can't access variables like tags within the sequence block, which is why this breaks.

Joshua Clayton

Disregard my last comment. You can access tags or any other variables inside the sequence just fine.

Here's a failure case:

  it "rand and a variable inside a factory" do
    define_model("User", :letters => :string)

    FactoryGirl.define do
      factory :user do
        tags = %w(one two three four five)

        sequence(:letters) do
          3.times.map { tags[rand(tags.length)] }
        end
      end
    end

    p FactoryGirl.build(:user).letters
  end

This fails with:

1) sequences rand and a variable inside a factory
     Failure/Error: 3.times.map { tags[rand(tags.length)] }
     TypeError:
       can't convert FactoryGirl::Declaration::Static into Integer
     # /Users/joshuaclayton/dev/gems/factory_girl/spec/acceptance/sequence_spec.rb:42:in `[]'
     # /Users/joshuaclayton/dev/gems/factory_girl/spec/acceptance/sequence_spec.rb:42
     # /Users/joshuaclayton/.rvm/gems/ruby-1.8.7-p352/gems/activemodel-3.1.0/lib/active_model/attribute_methods.rb:102:in `map'
     # /Users/joshuaclayton/.rvm/gems/ruby-1.8.7-p352/gems/activemodel-3.1.0/lib/active_model/attribute_methods.rb:102:in `each'
     # /Users/joshuaclayton/dev/gems/factory_girl/spec/acceptance/sequence_spec.rb:42:in `times'
     # /Users/joshuaclayton/dev/gems/factory_girl/spec/acceptance/sequence_spec.rb:42:in `each'
     # /Users/joshuaclayton/dev/gems/factory_girl/spec/acceptance/sequence_spec.rb:42:in `map'
     # /Users/joshuaclayton/dev/gems/factory_girl/spec/acceptance/sequence_spec.rb:42

That's what you were seeing.

Here's the fix:

  it "rand and a variable inside a factory" do
    define_model("User", :letters => :string)

    FactoryGirl.define do
      factory :user do
        tags = %w(one two three four five)

        sequence(:letters) do
          3.times.map { tags[Kernel.rand(tags.length)] }
        end
      end
    end

    p FactoryGirl.build(:user).letters
  end

Notice that the only difference is that I called Kernel.rand. Problem solved.

Rafael Dalmacio Schaer

ah, ok. Kernel.rand saves the deal.

May I ask, why this is like that, I try to understand the scope better.

Thnx a lot !!! For spending so much time on this.
It's strange, that once it doesn't work anymore as before.

Rafael Dalmacio Schaer

Actually, I can run it like that as well:

f.sequence(:tag_list) { Random.new.rand(1..5).times.map{ tags[Random.new.rand(tags.length)]}.join(", ") }

I even thought that was replaced by rand() to simplify

Joe Ferris
Owner
Rafael Dalmacio Schaer
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.