Class: MethodDefinitionQuestion

Inherits:
Question
  • Object
show all
Defined in:
lib/battleroom/models/method_definition_question.rb

Instance Attribute Summary collapse

Attributes inherited from Question

#answer_value, #data, #data_structure, #data_structure_class, #evaluation_scope, #explanation, #input_mechanism, #user_input, #variable_name, #variable_value

Instance Method Summary collapse

Methods inherited from Question

#congratulation_sequence, #enter_evaluation_loop, generate_question, #get_input, #handle_syntax_error_exceptions

Constructor Details

#initialize(scope) ⇒ MethodDefinitionQuestion

Returns a new instance of MethodDefinitionQuestion.



11
12
13
14
15
16
17
18
19
20
21
# File 'lib/battleroom/models/method_definition_question.rb', line 11

def initialize(scope)
  super(scope)
  @method_name = data[:method_name]
  @arg_count = data[:arg_count]
  @spec = data[:spec]
  @eval_string = data[:eval_string]
  @eval_answer = data[:eval_answer]
  @input_mechanism = 'pry'
  print_prompt
  evaluate_method_definition_input
end

Instance Attribute Details

#arg_countObject

Returns the value of attribute arg_count.



6
7
8
# File 'lib/battleroom/models/method_definition_question.rb', line 6

def arg_count
  @arg_count
end

#eval_answerObject

Returns the value of attribute eval_answer.



6
7
8
# File 'lib/battleroom/models/method_definition_question.rb', line 6

def eval_answer
  @eval_answer
end

#eval_stringObject

Returns the value of attribute eval_string.



6
7
8
# File 'lib/battleroom/models/method_definition_question.rb', line 6

def eval_string
  @eval_string
end

#method_nameObject

Returns the value of attribute method_name.



6
7
8
# File 'lib/battleroom/models/method_definition_question.rb', line 6

def method_name
  @method_name
end

#return_valueObject

Returns the value of attribute return_value.



6
7
8
# File 'lib/battleroom/models/method_definition_question.rb', line 6

def return_value
  @return_value
end

#specObject

Returns the value of attribute spec.



6
7
8
# File 'lib/battleroom/models/method_definition_question.rb', line 6

def spec
  @spec
end

#user_answer_verifiedObject

Returns the value of attribute user_answer_verified.



6
7
8
# File 'lib/battleroom/models/method_definition_question.rb', line 6

def user_answer_verified
  @user_answer_verified
end

Instance Method Details

#clean_eval_scope_of_method_definitionObject



69
70
71
72
73
# File 'lib/battleroom/models/method_definition_question.rb', line 69

def clean_eval_scope_of_method_definition
  if evaluation_scope.eval "respond_to?(:#{method_name}, true)"
    evaluation_scope.eval 'Object.class_eval("remove_method :' + method_name + '")'
  end
end

#evaluate_method_definition_inputObject



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/battleroom/models/method_definition_question.rb', line 75

def evaluate_method_definition_input
  enter_evaluation_loop do |user_submission|
    begin
      clean_eval_scope_of_method_definition
      # I want to make sure that the user's method isn't invoked if it uses the puts method
      if user_submission.include?('puts')
        print_puts_explanation
      else
        evaluation_scope.eval(user_submission)
        return_value = evaluation_scope.eval(eval_string)
        if (return_value == eval_answer)
          self.user_answer_verified = user_submission
          true
        else
          handle_incorrect_method_definition(return_value)
        end
      end
    rescue ArgumentError => e
      print_argument_error_prompt(e)
    rescue NoMethodError => e
      print_wrong_method_error(e, user_submission)
    rescue NameError => e
      handle_name_error_exceptions(e, user_submission)
    end
  end
end

#fresh_bindingObject



49
50
51
# File 'lib/battleroom/models/method_definition_question.rb', line 49

def fresh_binding
  binding
end

#handle_incorrect_method_definition(return_value) ⇒ Object



35
36
37
# File 'lib/battleroom/models/method_definition_question.rb', line 35

def handle_incorrect_method_definition(return_value)
  battleprint "\nWhen invoking your method via ".red + eval_string + ", your method returned #{return_value || 'nil'}. It should have returned #{eval_answer}. Try again.\n".red
end

#handle_name_error_exceptions(error, user_submission) ⇒ Object



27
28
29
30
31
32
33
# File 'lib/battleroom/models/method_definition_question.rb', line 27

def handle_name_error_exceptions(error, user_submission)
  if user_submission.include?('def') == false
    print_no_method_error_prompt
  else
    print_colorized_error_prompt(error)
  end
end


62
63
64
65
66
67
# File 'lib/battleroom/models/method_definition_question.rb', line 62

def print_argument_error_prompt(e)
  e.message.match(/wrong number of arguments \((\d) for (\d)\)/)
  passed_arg_count = $1.to_i
  expected_arg_count = $2.to_i
  battleprint "\nLooks like you defined #{method_name} to take #{expected_arg_count} argument(s), when it should take #{arg_count}. Try again.\n".red
end


43
44
45
46
47
# File 'lib/battleroom/models/method_definition_question.rb', line 43

def print_no_method_error_prompt
  battleprint "\nYou just trigged a common Ruby error that reads: \n".red
  battleprint "\tundefined method \'WHATEVER_METHOD_YOU_TRIED_TO_INVOKE\'\n".green
  battleprint "Basically, you tried to use a method before you defined it, and Ruby said, \"You haven't told me how to do that yet.\" To let Ruby know that you're defining a method, you'll use the the \"def\" keyword, followed by the desired method name, and in many cases an optional list of arguments between parentheses. Once you've finished writing the method's inner code, you'll let Ruby know that your method definition is finished by using the \"end\" keyword.\n".red
end


23
24
25
# File 'lib/battleroom/models/method_definition_question.rb', line 23

def print_prompt
  battleprint('Define a method called '.blue + method_name.yellow +  ' that takes '.blue + arg_count.to_s.yellow + " argument(s) and #{spec}.\n".blue)
end


39
40
41
# File 'lib/battleroom/models/method_definition_question.rb', line 39

def print_puts_explanation
  battleprint 'The last line of your method definition uses Ruby\'s "puts" method. The "puts" method is helpful for logging errors and statuses to the console, but its actual '.red + "return".red.underline + " value is always nil, and thus your method returns nil. Try again, this time without using \"puts\".\n".red
end


53
54
55
56
57
58
59
60
# File 'lib/battleroom/models/method_definition_question.rb', line 53

def print_wrong_method_error(error, user_submission)
  definition_pattern = Regexp.new("def\s*#{method_name}")
  if user_submission.match(definition_pattern)
    handle_incorrect_method_definition(user_submission)
  else
    battleprint "\nYou defined the wrong method, probably as the result of a mispelling. Try again.".red
  end
end