views:

110

answers:

3

This is my Action model:

class Action < ActiveRecord::Base
end

class Fold < Action
end

class Check < Action
end

class Call < Action
end

class Bet < Action
end

In another model, I have this

class Deal < ActiveRecord::Base
  def Deal.parse_action(action_string)
    case action_string
    when "folds":   Fold.new()
    when "checks":  Check.new()
    when "calls":   Call.new()
    when "bets":    Bet.new()
    when "raises":  Bet.new()
    else nil   
    end
  end
  # ...
end

Now, when I test this if this works in my unit tests, everything appears to work. But as soon as I start the web server in development mode, I get this:

NameError (uninitialized constant Deal::Fold):
  app/models/deal.rb:115:in `parse_action'
  ...

Why does it think Fold exists within the namespace Deal? And why does this not happen in the test environment?

+1  A: 

It's not saying that Fold exists in the Deal namespace, it's saying that it's looking for the constant Fold and it's currently inside Deal. For example, try this:

class Foo 
  def test; puts Bar; end
end
Foo.new.test

and you'll get this:

NameError: uninitialized constant Foo::Bar
  from (irb):3:in `test'
  from (irb):7
  from :0

Rails has stuff to auto-load constants for you and I'm guessing the problem is that you don't have the Fold class in its own file. Try putting the Fold class definition into it's own file -- app/models/fold.rb and see if that helps. If so, try putting it back in the action.rb file and then doing something that would cause the Action file to load before you do the case statement, like x = Action right before the case statment. If that works then you need to require "action.rb" in deal.rb because the issue is that your test code is loading action.rb (possibly through some other test) but your production code isn't.

Jordan Brough
You could just require action in deal.rb.
ScottD
A: 

In Ruby to add a method to a class you have declare like so:

  class Deal < ActiveRecord::Base
    def self.parse_action(action_string)
      case action_string
        when "folds":   Fold.new
        ....

That may be the source of your problems as well.

Also (sorry to nit pick) but you don't need the parenthesis on Fold.new. You are able to pass parameters to methods without using parathesis.

vrish88
http://blog.jayfields.com/2007/10/ruby-defining-class-methods.html says There's More Than One Way To Do It.
Andrew Grimm
BTW, did you mean "without using parentheses"?
Andrew Grimm
A: 

I don't use Rails at work, but I sometimes come across the scenario of a class being known when I'm running tests, but not when I'm running the executable. That happens because I have the requisite "require" statements in my test files for the relevant files, but I hadn't got around to putting the requisite "require" statements in production code.

Andrew Grimm
This worked for me. I just has to 'require "action.rb"' in the Deal model.
KaptajnKold