1

I have a conditional bit of code that only can be loaded under certain conditions. It's platform specific code.

module MyGem
  module MyPlatformSpecificThing
    #stuff
  end
end

My current attempt at lazily requiring this is performed like:

module MyGem
  class AClass

  def DoSomething
    if thing_is_true
      require 'my_platform_specific_thing.rb'
      MyGem::MyPlatformSpecificThing.init
      #more stuff
    end
    #even more stuff
  end
end

This seemed like a solid enough plan, unfortunately it is not working. This code results in an error:

uninitialized constant MyGem::MyPlatformSpecificThing (NameError)

The stack trace indicates the source of the error is the call to init within the DoSomething method.

I am not entirely sure why Ruby is giving me fits here. What am I doing wrong, and how should I be doing this?

edit:

For specifics, I'm referring to the Platform class located here. The above should help narrow down the details of what I'm referring to, but in case anyone wanted/needed to see the specific classes/modules I'm work with.

Jason Whitehorn
  • 13,585
  • 9
  • 54
  • 68
  • To the person who voted to close this question as "unclear as what is being asked"; I am pretty sure I spelled that out in the question, but if there is a specific aspect of this I can elaborate on please do let me know. – Jason Whitehorn Sep 17 '13 at 13:06
  • can you elaborate on what `thing_is_true` checking? does it have to be in an instance of `AClass`? If you can move it out of instance, then I would recommend doing require on class level and not instance level. – Iuri G. Sep 19 '13 at 20:29
  • Sure. The actual check is checking a class variable to see if it's null. I am not sure I am following the last part of moving the require to the class level, could you elaborate a little more on that? – Jason Whitehorn Sep 19 '13 at 20:39
  • FWIW, AClass was simply a stripped down version of this -> https://github.com/jwhitehorn/pi_piper/blob/develop/lib/pi_piper/platform.rb – Jason Whitehorn Sep 19 '13 at 20:39
  • by class level I meant move it out from instance method into class declaration or module declaration: https://gist.github.com/igagnidz/54d846e984f620b3c5a3 – Iuri G. Sep 19 '13 at 20:50
  • Ok, I see what you mean. Unfortunately I do not see immediately how that is possible. You see the DoSomething method in this case is a factory and is delaying the loading of a platform specific gem. Under certain cases (e.g. unit testing) I do _not_ want the platform specific gem loaded. Under those scenarios the factory has a mock injected into it. See the link I posted for the specifics I'm working from. – Jason Whitehorn Sep 20 '13 at 03:32
  • `require` actually needs the file name without `.rb`, i.e. `require 'my_platform_specific_thing'`. Could this be the cause of the problem? Are you doing a `rescue LoadError` somewhere in your actual code that may prevent a potential `LoadError` from bubbling up? – Patrick Oscity Sep 20 '13 at 10:44
  • @p11y I've used 'class.rb' before in require... but, I will admit that's one thing I haven't tried. I'll give it a try and let you know. – Jason Whitehorn Sep 20 '13 at 22:15

3 Answers3

1

You've almost got it right. Remember that the require method loads relative to the load path. As you're making a gem you've added the gem lib directory to the load path. Change the require to:

require 'my_gem/bcm2835'

Or for PiPiper:

require 'pi_piper/bcm2835'

This should load only when a driver hasn't been set.

orien
  • 2,130
  • 16
  • 20
0

Your pseudo-code is bit incomplete and confusing, but I think this may be the problem. If I am mistaken, seeing your real code as complete as necessary could help.

Check this response as a reference.

Your example shows:

MyGem::MyPlatformSpecificThing.init

However, that format should have Module::Class.method. Your sample shows Module::Module.method.

The error message

uninitialized constant

is very specific in that it is recognizing the call as a constant, not a class.

Community
  • 1
  • 1
Richard_G
  • 4,700
  • 3
  • 42
  • 78
  • For completeness "my real code" was linked to in the question. Look under the "edit" section at the bottom. - I am not sure this is a solution at all... I will review, but I'm pretty sure I understand what `::` does ;-) – Jason Whitehorn Sep 20 '13 at 22:09
  • BTW, it's a module level function I'm calling, so it'd be Module::Module.method... not Module::Class.method. – Jason Whitehorn Sep 20 '13 at 22:10
  • I saw the PiPiper code. And, I saw how you modified it. I don't see the init method. Regardless, I believe there is an issue in the definition that is driving the problem since the error indicates an invalid reference to a constant. Just trying to help here, so please accept it in that light. Thanks. – Richard_G Sep 20 '13 at 22:46
  • Thank you, I understand and appreciate the help! – Jason Whitehorn Sep 21 '13 at 16:04
-1

The error you've specified...

uninitialized constant MyGem::MyPlatformSpecificThing (NameError)

... will only occur if the inner module (PiPiper::Bcm2835) is never actually defined; if the problem was with the actual call to the module function (init), you'd get a different error.

I notice you've commented out the require on line 10, platform.rb:

#require 'bcm2835.rb'

... and required the file elsewhere. Let me guess, this is solving your problem, no?

Taking another look, in its original form the require statement should have failed, unless you've already added the pi_piper directory to $LOAD_PATH. Try changing the lazy require to this:

require './bcm2835.rb'

But note that this will not work either if you change the working directory (Dir.chdir) at any point prior to executing this line.

user1974458
  • 87
  • 1
  • 6
  • For future visitors, this is _NOT_ the correct answer. The site reordered the results causing this to incorrectly receive the bounty. – Jason Whitehorn Sep 24 '13 at 04:05
  • I'll gladly hand over the bounty to the intended user if that's possible. If you felt someone did a better job of answering the question, that's up to you. But voting it down? What part did you feel was incorrect?? – user1974458 Sep 24 '13 at 15:26