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, #initialize

Constructor Details

This class inherits a constructor from Question

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



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

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



74
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
# File 'lib/battleroom/models/method_definition_question.rb', line 74

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



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

def fresh_binding
  binding
end

#handle_incorrect_method_definition(return_value) ⇒ Object



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

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



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

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

#post_initializeObject



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

def post_initialize
  @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


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

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


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

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


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

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


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

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


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

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