Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing included class's protected constant in a ActiveSupport::Concern

What's the simplest way to access included class's protected constant in the ActiveSupport::Concern context?

Example classes:

module Printable
    extend ActiveSupport::Concern

private
    def print_constant
        puts MY_CONSTANT
    end
end

class Printer
    include Printable

    def print
        print_constant
    end

private
    MY_CONSTANT = 'Hello'.freeze
end

This solution produces an error:

NameError: uninitialized constant Printable::MY_CONSTANT

I'm aware of an alternative that seems to work:

puts self.class::MY_CONSTANT

But, it doesn't feel right. :-)

Any better suggestions?

like image 255
Tonči D. Avatar asked Sep 30 '14 12:09

Tonči D.


2 Answers

First of all, you should put #print_constant into an included block:

module Printable
  extend ActiveSupport::Concern

  included do
    private

    def print_constant
      puts MY_CONSTANT
    end
  end
end

Now there are at least two ways of accessing the class constant MY_CONSTANT:

  1. #included yields with a base parameter similar to Ruby's #included:

    module Printable
      extend ActiveSupport::Concern
    
      included do |base|
        private
    
        define_method :print_constant do
          puts base::MY_CONSTANT
        end
      end
    end
    
  2. Another method is going from self.class:

    module Printable
      extend ActiveSupport::Concern
    
      included do
        private
    
        def print_constant
          puts self.class::MY_CONSTANT
        end
      end
    end
    

ActiveSupport Concern Documentation

like image 63
Halil Özgür Avatar answered Nov 06 '22 14:11

Halil Özgür


Accessing a constant of an including class from a concern isn't really a good idea.

A concern shouldn't have (too much) knowledge of the classes it's included in.

I would go for a common API in the concern and override when needed... like this:

module Printable
    extend ActiveSupport::Concern

private
    def print
      puts ""
    end
end

class Printer
    include Printable

    def print
        MY_CONSTANT
    end

private
    MY_CONSTANT = 'Hello'.freeze
end
like image 20
skahlert Avatar answered Nov 06 '22 14:11

skahlert