4

I'm writing some tests to verify the behaviour of some regular expressions to be used within a Ruby console application. I'm trying to define constant class level fields on a class not meant to be instantiated (just supposed to have constant RE values defined on it. I'm having trouble defining this properly using Ruby idiom (I have C++/C# background).

First I tried to define a class constant

class Expressions
  # error is on following line (undefined method DATE)
  Expressions.DATE = /(?<Year>\d{4})-(?<Month>\d{2})-(?<Day>\d{2})/

end

class MyTest < Test::Unit::TestCase
  def setup
    @expression = Expressions::DATE
  end

  def test
    assert "1970-01-01" =~ @expression
  end
end

this just produces error: undefined method `DATE=' for Expressions:Class (NoMethodError)

Next I tried class attributes:

class Expressions
  @@Expressions.DATE = /(?<Year>\d{4})-(?<Month>\d{2})-(?<Day>\d{2})/ 
end

class MyTest < Test::Unit::TestCase
  def setup
    # NameError: uninitialized constant Expressions::DATE here:
    @expression = Expressions::DATE
  end

  def test
    assert "1970-01-01" =~ @expression
  end
end

This produces an NameError: uninitialized constant Expressions::DATE error.

I know I could just define attributes on a class to be used as an instance, but this is inefficient and not a correct solution to the problem (just a hack). (In C++ I would use a static const, done)

So I'm stuck really. I need to know what is the correct way in Ruby to define constant regular expressions that need to be used in other classes. I'm having a problem with the definition, initialisation and its use,

thanks.

Plastikfan
  • 3,674
  • 7
  • 39
  • 54
  • mmm, I've just discovered the BEGIN statement which defines functionality to be run before program starts. Is this where you could initialise constants? – Plastikfan Feb 18 '15 at 10:10

1 Answers1

6

A constant in Ruby is like a variable, except that its value is supposed to remain constant for the duration of a program. The Ruby interpreter does not actually enforce the constancy of constants, but it does issue a warning if a program changes the value of a constant. Lexically, the names of constants look like the names of local variables, except that they begin with a capital letter. By convention, most constants are written in all uppercase with underscores to separate words, LIKE_THIS. Ruby class and module names are also constants, but they are conventionally written using initial capital letters and camel case, LikeThis.

The Ruby Programming Language: David Flanagan; Yukihiro Matsumoto.

This should work:

class Expressions
  DATE = /.../
end

class MyTest < Test::Unit::TestCase
  def setup
    @expression = Expressions::DATE
  end
  # ...
end
Vitalii Elenhaupt
  • 7,146
  • 3
  • 27
  • 43
  • That's great and exactly what I needed. I can't believe that all the combinations I tried, this one was not one of them. So the fact that an identifier starts with a capital letter inside a class, automatically makes it class level without having to prefix with @@. Is that correct? – Plastikfan Feb 18 '15 at 10:41
  • 1
    @Shantaram yes, that is correct. Here is relevant question regarding class variables and constants http://stackoverflow.com/questions/5890118/what-does-variable-mean-in-ruby – Vitalii Elenhaupt Feb 19 '15 at 11:08