`load_missing_constant': uninitialized constant Rails::Generator (NameError)

Hello,
    I'm probably missing something pretty basic here as a rails newbie but I'm trying to write a plugin and I am trying to get my generator to work.

I am trying to call the manifest method in my vendor/plugins/media_module/generators/media_module_generator.rb from my vendor/plugins/media_module/init.rb.

here's the code in vendor/plugins/media_module/init.rb:
[code]
require File.join(File.dirname(__FILE__), '/generators/media_module_generator')
media_mod_generatore = MediaModuleGenerator.new
media_mod_generatore::manifest()
[/code]

and here's my code in vendor/plugins/media_module/generators/media_module_generator.rb:
[code]
class MediaModuleGenerator < Rails::Generator::NamedBase
  def manifest
    record do |m|
      m.file "media_controller.rb", "app/controllers/media_controller.rb"
      m.file "media.rb", "app/models/media.rb"
    end
  end
end
[/code]

When I restart my server I get this:
`load_missing_constant': uninitialized constant Rails::Generator (NameError)

Thanks,
Clem C
clemcrockAsked:
Who is Participating?
 
cminearConnect With a Mentor Commented:
I think I see the problem, but it would be nice if you also said which specific line the error occurred on.  I believe it's hiccupping on:
   self.spec.path = File.dirname(__FILE__) + '/generators/media_module'    
but I could also see it having a problem with:
   @source_root = options[:source] || File.join(spec.path, 'templates')

Just to be clear, is the 'class Base' your code or are you just copying that above from the 'rails_generator/base.rb' file from the Rails gem code?  (If it's your code, then that could be the problem, but I'll assume you copied it into your response.)

With the first possible issue, the problem is likely just as it said: self.spec has not been defined yet, so it considers it to be nil.  Nil does not understand the 'path' method, and thus you get the NoMethodError.  However, even if 'self.spec' were set to be a Rails::Generator::Spec, looking at that code, the 'path' variable is only set to be a reader, so any attempt to set it would probably throw a different error.

To be honest, I am not immediately discerning how the Spec is created for the Rails::Generator::Base object.  But my guess is that it gets set as part of being called as a command.

Do you have a 'media_module_generator' script, yet, similar to what Rails provides in the 'script' directory?  If you do not, I'd recommend creating it.  Then, instead of trying to deal with the MediaModuleGenerator from within a Ruby/Rails program file, start it similar to how a user would.  
   system("location/to/script/media_module_generator")
You could probably put this line somewhere in config/boot.rb file so that it would be run every time you start the Rails application (which is what you said you want).
0
 
cminearCommented:
I have never created a Rails plugin myself, but looking at the error, the obvious thought that comes to me is that nothing has imported 'rails_generator', so the ruby environment does not know about the Rails::Generator class (much less Rails::Generator::NamedBase).  

If you look at the 'script/generate' script, it requires 'commands/generate'.  You then look at lib/commands/generate.rb (wherever your rails gem is installed) and it requires 'rails_generator'.

Try adding the line:
  require 'rails_generator'
at the top of vendor/plugins/media_module/generators/media_module_generator.rb.  I would put it in that file because that is where it is needed.

The next issue may be whether you really want the generator to run _every_ time you start your server.  That may not be the behavior you want, or you've already considered that and your generator accounts for it.  (As I said, I've never created a plugin, so I'm not an expert on that.)
0
 
clemcrockAuthor Commented:
Thanks a lot for the help.    For development purposes, I wanted the generator to run everytime I restarted the server.   I realize this is not very necessary but I am more interested in making this work just for pure knowledge sake.     I required the rails_generator a the top of media_module_generator.rb and now when I restart the server, I get this:

media_module/init.rb:35:in `initialize': wrong number of arguments (0 for 1) (ArgumentError)

I'm not understanding this too well as I didn't think a class of Rails::Generator::Base took arguments.

Thanks again.
0
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

 
cminearCommented:
It's not that Rails::Generator::Base takes arguments (it's a class), but that the 'new' class method does.  So does Rails:::Generator::NamedBase's 'new' class method.  Both of them accept 'runtime_args' and 'runtime_options'; the 'runtime_options' defaults to an empty hash.  But it would appear the 'runtime_args' variable needs to be specified.  

When you run the Rails-provied 'script/generate', it ultimately passes in ARGV to the invocation of the 'new' method.  However, when you have this statement in 'init.rb':
   media_mod_generatore = MediaModuleGenerator.new
You aren't passing in anything.  Thus, you get the error about the "wrong number of arguments".

You have two options.  Pass in an array of arguments that you'd like your generator to be able to handle, or create your own 'new' class method for MediaModuleGenerator which will override the 'new' method provided by the parent.
0
 
clemcrockAuthor Commented:
I got past that point by doing exactly like you expected as you can see here:

[code]
media_module = MediaModuleGenerator.new({})
media_module.manifest
[/code]

I got past this sticking point and now I'm getting this problem:

When I run my generator, I get this error:

You have a nil object when you didn't expect it! (NoMethodError) The error occurred while evaluating nil.path

Here's my code:
class Base
  include Options
  class_inheritable_accessor :spec

  def initialize(runtime_args, runtime_options = {})
    @args = runtime_args
    parse!(@args, runtime_options)
 
    # Derive source and destination paths.
    @source_root = options[:source] || File.join(spec.path, 'templates')
  end
end

class MediaModuleGenerator < Rails::Generator::Base
  def initialize(runtime_args, runtime_options = {})
     self.spec.path = File.dirname(__FILE__) + '/generators/media_module'    
     super
  end
end
[/code]

So when I set the self.spec.path var to  File.dirname(__FILE__) + '/generators/media_module', it's not registering in the base class.

Thanks again for your help
0
 
clemcrockAuthor Commented:
Thanks for your help.   You are correct that the base class is coming from the rails_generator/base.rb module.  I do like the idea of putting the code in the config/boot file but I really would like to learn if it's possible to set a base class attribute from an overridden function in a subclass?    I can't seem to find any information or examples on how to do this.

I do have a media_module_generator.rb set and I can call it from the command line and it works perfectly.   This problem has turned into a lesson in ruby class inheritance.

Again - very grateful for your help



0
 
clemcrockAuthor Commented:
Thanks for your help.   You are correct that the base class is coming from the rails_generator/base.rb module.  I do like the idea of putting the code in the config/boot file but I really would like to learn if it's possible to set a base class attribute from an overridden function in a subclass?    I can't seem to find any information or examples on how to do this.

I do have a media_module_generator.rb set and I can call it from the command line and it works perfectly.   This problem has turned into a lesson in ruby class inheritance.

Again - very grateful for your help
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.