Trần Kim Dự
Trần Kim Dự

Reputation: 6102

Included module cannot call instance variable of parent class

For example, I have a class that defined a instance variable:

 class ApplicationApi < Grape::API
    include WithGrapeLogging
    @api_environment_name = "Android"
  end

Here is my custom module, in this custom module, I called instance variable of above class:

require 'grape_logging'
module WithGrapeLogging
  extend ActiveSupport::Concern
  included do
      logger.formatter = GrapeLogging::Formatters::Default.new

      use GrapeLogging::Middleware::RequestLogger,
        logger: logger,
        formatter: GrapeLoggerFormatter.new(@api_environment_name),
        include: [ GrapeLogging::Loggers::Response.new,
                   GrapeLogging::Loggers::FilterParameters.new,
                   GrapeLogging::Loggers::ClientEnv.new,
                   GrapeLogging::Loggers::RequestHeaders.new ]
  end
end

I don't know what that variable is null. Please figure me how.

Upvotes: 1

Views: 163

Answers (1)

Piccolo
Piccolo

Reputation: 1666

Let's take a look at the Module#include method's source code:

               static VALUE
rb_mod_include(int argc, VALUE *argv, VALUE module)
{
    int i;
    ID id_append_features, id_included;

    CONST_ID(id_append_features, "append_features");
    CONST_ID(id_included, "included");

    for (i = 0; i < argc; i++)
        Check_Type(argv[i], T_MODULE);
    while (argc--) {
        rb_funcall(argv[argc], id_append_features, 1, module);
        rb_funcall(argv[argc], id_included, 1, module);
    }
    return module;
}

We can see that for each of the arguments passed to Module#include, it calls the block passed to included (via rb_funcall)

When you include your module on the second line of your class definition, it calls the block provided to included in your module definition. When it's running through that block, Ruby identifies that @api_environment_name has not been defined and throws an error. If you put the definition of that instance variable before you include the module, it will recognize it.

Upvotes: 1

Related Questions