Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby Koans #75 test_constants_become_symbols, correct answer?

Tags:

symbols

ruby

My question builds upon this question: Ruby Koan: Constants become symbols. I have the following code:

in_ruby_version("mri") do
  RubyConstant = "What is the sound of one hand clapping?"
  def test_constants_become_symbols
    all_symbols = Symbol.all_symbols

    assert_equal __, all_symbols.include?(__)
  end
end

Is the correct answer supposed to be the following?

    assert_equal true, all_symbols.include?("RubyConstant".to_sym)

I know I shouldn't just do this:

    assert_equal true, all_symbols.include?(:RubyConstant)

because then I could put anything in there and it would still be true

    assert_equal true, all_symbols.include?(:DoesNotMatter)

Apologies in advance for asking simple a "yes or no" question. I was curious as to know what the "right" answer is. I would have preferred to just ask this question in the comments in the previous post I mentioned above but I couldn't without making a separate post.

like image 798
Joonha Shin Avatar asked Nov 08 '12 18:11

Joonha Shin


2 Answers

Here's what I got:

in_ruby_version("mri") do
  RubyConstant = "What is the sound of one hand clapping?"
  def test_constants_become_symbols
    all_symbols_as_strings = Symbol.all_symbols.map { |x| x.to_s }

    assert_equal true, all_symbols_as_strings.include?("RubyConstant")
  end
end
like image 54
Eyal Golan Avatar answered Sep 30 '22 10:09

Eyal Golan


NOTE: the following answer only applies to environments like irb, where Ruby code is being executed line by line. When executing code in a file, Ruby scans the entire file for symbols before executing anything, so the following details are not accurate. I've not deleted this answer because it exposes an interesting edge case, but see @GlichMr's answer for a better explanation of the problem.

You can safely do the following, because Symbol.all_symbols returns a copy of the array of symbols, not a reference.

assert_equal true, all_symbols.include?(:RubyConstant)

I think that is the intended answer to the koan, and it's why all_symbols is defined rather than calling Symbol.all_symbols directly. For some evidence, see the following:

>> X = 1
=> 1
>> all_symbols = Symbol.all_symbols; nil
=> nil
>> Y = 2
=> 2
>> all_symbols.include?(:X)
=> true
>> all_symbols.include?(:Y)
=> false

Using String#to_sym would make it possible to make these calls against Symbol.all_symbols directly, but is not necessary for solving this koan.

like image 37
Gregory Brown Avatar answered Sep 30 '22 10:09

Gregory Brown