Skip to content
This repository was archived by the owner on Jan 17, 2019. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions lib/app/routes/exercises.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ module Xapi
module Routes
class Exercises < Core
helpers do
def render_homework(method)
def render_homework(method, *args)
require_key
pg :exercises, locals: {exercises: Xapi::UserHomework.send(method, params[:key])}
pg :exercises, locals: {exercises: Xapi::UserHomework.send(method, params[:key], *args)}
end
end

Expand All @@ -16,6 +16,10 @@ def render_homework(method)
render_homework(:restore)
end

get '/exercises/:language' do |language|
render_homework(:all_exercises_by_language_for, language)
end

get '/exercises/:language/:slug' do |language, slug|
exercise = Exercise.new(language, slug)
if exercise.not_found?
Expand Down
5 changes: 5 additions & 0 deletions lib/xapi/user_homework.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ def self.all_exercises_for(key)
extract ExercismIO.all_exercises_for(key)
end

def self.all_exercises_by_language_for(key, language)
exercises = extract ExercismIO.exercises_for(key)
exercises.select { |exercise| exercise.language == language }
end

def self.code_for(key)
iterations = ExercismIO.code_for(key)
iterations.map {|iteration| Iteration.new(iteration)}.sort_by {|iteration|
Expand Down
22 changes: 22 additions & 0 deletions test/app/routes/exercises_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ def test_get_specific_exercise
Approvals.verify(last_response.body, options)
end

def test_require_key_to_fetch_exercises_for_language
get '/exercises/ruby'

assert_equal 401, last_response.status
end

def test_require_key_to_fetch_exercises
get '/exercises'

Expand All @@ -41,6 +47,22 @@ def test_require_key_to_restore_exercises
# Acceptance tests. Relies on real language-specific data.
# Expect it to fail regularly, since exercises get updated fairly frequently.

def test_get_exercises_by_language
VCR.use_cassette('exercism_api_current_exercises') do
get '/exercises/ruby', :key => 'abc123'
options = {:format => :json, :name => 'get_current_exercises_by_language'}
Approvals.verify(last_response.body, options)
end
end

def test_handle_missing_exercise_by_language
VCR.use_cassette('exercism_api_current_exercises_with_error') do
get '/exercises/ruby', :key => 'xyz456'
options = {:format => :json, :name => 'get_current_exercises_with_error_by_language'}
Approvals.verify(last_response.body, options)
end
end

def test_get_exercises
VCR.use_cassette('exercism_api_current_exercises') do
get '/exercises', :key => 'abc123'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"assignments": [
{
"track": "ruby",
"slug": "anagram",
"files": {
"anagram_test.rb": "require 'minitest/autorun'\nrequire_relative 'anagram'\n\nclass AnagramTest < MiniTest::Unit::TestCase\n\n def test_no_matches\n detector = Anagram.new('diaper')\n assert_equal [], detector.match(%w(hello world zombies pants))\n end\n\n def test_detect_simple_anagram\n skip\n detector = Anagram.new('ant')\n anagrams = detector.match(['tan', 'stand', 'at'])\n assert_equal ['tan'], anagrams\n end\n\n def test_detect_multiple_anagrams\n skip\n detector = Anagram.new('master')\n anagrams = detector.match(['stream', 'pigeon', 'maters'])\n assert_equal ['maters', 'stream'], anagrams.sort\n end\n\n def test_does_not_confuse_different_duplicates\n skip\n detector = Anagram.new('galea')\n assert_equal [], detector.match(['eagle'])\n end\n\n def test_identical_word_is_not_anagram\n skip\n detector = Anagram.new('corn')\n anagrams = detector.match %w(corn dark Corn rank CORN cron park)\n assert_equal ['cron'], anagrams\n end\n\n def test_eliminate_anagrams_with_same_checksum\n skip\n detector = Anagram.new('mass')\n assert_equal [], detector.match(['last'])\n end\n\n def test_eliminate_anagram_subsets\n skip\n detector = Anagram.new('good')\n assert_equal [], detector.match(['dog', 'goody'])\n end\n\n def test_detect_anagram\n skip\n detector = Anagram.new('listen')\n anagrams = detector.match %w(enlists google inlets banana)\n assert_equal ['inlets'], anagrams\n end\n\n def test_multiple_anagrams\n skip\n detector = Anagram.new('allergy')\n anagrams = detector.match %w(gallery ballerina regally clergy largely leading)\n assert_equal ['gallery', 'largely', 'regally'], anagrams.sort\n end\n\n def test_anagrams_are_case_insensitive\n skip\n detector = Anagram.new('Orchestra')\n anagrams = detector.match %w(cashregister Carthorse radishes)\n assert_equal ['Carthorse'], anagrams\n end\nend\n",
"README.md": "# Anagram\n\nWrite a program that, given a word and a list of possible anagrams, selects the correct sublist.\n\nGiven `\"listen\"` and a list of candidates like `\"enlists\" \"google\" \"inlets\" \"banana\"` the program should return a list containing `\"inlets\"`.\n\n\n## Source\n\nInspired by the Extreme Startup game [view source](https://github.com/rchatley/extreme_startup)\n"
},
"fresh": false,
"readme": "Please upgrade to the latest version of the exercism command-line client. See: http://cli.exercism.io",
"test_file": "PLEASE_UPGRADE.txt",
"tests": "Please upgrade to the latest version of the exercism command-line client. See: http://cli.exercism.io"
},
{
"track": "ruby",
"slug": "bob",
"files": {
"bob_test.rb": "require 'minitest/autorun'\n\nbegin\n require_relative 'bob'\nrescue LoadError => e\n eval(\"\\\"#{DATA.read}\\n\\\"\").split(\"\\n.\\n\").each_with_index do |s,i|\n if i > 0\n puts \"\\t--- press enter to continue ---\"\n gets\n end\n puts \"\\n\\n\", s, \"\\n\\n\\n\"\n end\n exit!\nend\n\nclass TeenagerTest < MiniTest::Unit::TestCase\n attr_reader :teenager\n\n def setup\n @teenager = ::Bob.new\n end\n\n def test_stating_something\n assert_equal 'Whatever.', teenager.hey('Tom-ay-to, tom-aaaah-to.')\n end\n\n def test_shouting\n skip\n assert_equal 'Woah, chill out!', teenager.hey('WATCH OUT!')\n end\n\n def test_shouting_gibberish\n skip\n gibberish = ('A'..'Z').to_a.shuffle[0,10].join\n assert_equal 'Woah, chill out!', teenager.hey(gibberish)\n end\n\n def test_asking_a_question\n skip\n assert_equal 'Sure.', teenager.hey('Does this cryogenic chamber make me look fat?')\n end\n\n def test_asking_a_numeric_question\n skip\n assert_equal 'Sure.', teenager.hey('You are, what, like 15?')\n end\n\n def test_asking_gibberish\n skip\n gibberish = ('a'..'z').to_a.shuffle[0,10].join\n assert_equal 'Sure.', teenager.hey(\"#{gibberish}?\")\n end\n\n def test_talking_forcefully\n skip\n assert_equal 'Whatever.', teenager.hey(\"Let's go make out behind the gym!\")\n end\n\n def test_using_acronyms_in_regular_speech\n skip\n assert_equal 'Whatever.', teenager.hey(\"It's OK if you don't want to go to the DMV.\")\n end\n\n def test_forceful_questions\n skip\n assert_equal 'Woah, chill out!', teenager.hey('WHAT THE HELL WERE YOU THINKING?')\n end\n\n def test_shouting_numbers\n skip\n assert_equal 'Woah, chill out!', teenager.hey('1, 2, 3 GO!')\n end\n\n def test_only_numbers\n skip\n assert_equal 'Whatever.', teenager.hey('1, 2, 3')\n end\n\n def test_question_with_only_numbers\n skip\n assert_equal 'Sure.', teenager.hey('4?')\n end\n\n def test_shouting_with_special_characters\n skip\n assert_equal 'Woah, chill out!', teenager.hey('ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!')\n end\n\n def test_shouting_with_no_exclamation_mark\n skip\n assert_equal 'Woah, chill out!', teenager.hey('I HATE YOU')\n end\n\n def test_statement_containing_question_mark\n skip\n assert_equal 'Whatever.', teenager.hey('Ending with ? means a question.')\n end\n\n def test_prattling_on\n skip\n assert_equal 'Sure.', teenager.hey(\"Wait! Hang on. Are you going to be OK?\")\n end\n\n def test_silence\n skip\n assert_equal 'Fine. Be that way!', teenager.hey('')\n end\n\n def test_prolonged_silence\n skip\n silence = \" \" * rand(1..10)\n assert_equal 'Fine. Be that way!', teenager.hey(silence)\n end\n\n def test_on_multiple_line_questions\n skip\n assert_equal 'Whatever.', teenager.hey(%{\nDoes this cryogenic chamber make me look fat?\nno})\n end\nend\n__END__\n\n######## ######## ######## ####### ########\n## ## ## ## ## ## ## ## ##\n## ## ## ## ## ## ## ## ##\n###### ######## ######## ## ## ########\n## ## ## ## ## ## ## ## ##\n## ## ## ## ## ## ## ## ##\n######## ## ## ## ## ####### ## ##\n\n\n#{e.backtrace.first} #{e.message}\n\nWelcome to your first ruby Exercism exercise! This is your first error message.\n.\nFirst it tells you the name of the file where the error is occurring:\n\n bob_test.rb\n.\nThen it tells you which line that error is on:\n\n bob_test.rb:4\n.\nAfter that, it tells you the name of the method where the error is occurring:\n\n in `require_relative'\n.\nNext, it tells you exactly what the error is:\n\n #{e.message.split('--').first}\n.\nFinally, it tells you which file is missing:\n\n #{e.message.split('--').last}\n.\nSo the error is there on line 4 of this file (bob_test.rb). What's on line 4?\n\n require_relative 'bob'\n\nWe are trying to require the file, and it isn't there.\n.\nYou can fix the problem by creating an empty file named bob.rb inside\nof the ruby/bob directory.\n\nThen run this test again (ruby bob_test.rb). Make all the tests pass,\nand submit your solution (exercism submit bob.rb).\n\nMore instructions are in README.md in this directory. Good luck!\n",
"README.md": "# Bob\n\nBob is a lackadaisical teenager. In conversation, his responses are very limited.\n\nBob answers 'Sure.' if you ask him a question.\n\nHe answers 'Woah, chill out!' if you yell at him.\n\nHe says 'Fine. Be that way!' if you address him without actually saying anything.\n\nHe answers 'Whatever.' to anything else.\n\n## Instructions\n\nRun the test file, and fix each of the errors in turn. When you get the first test to pass, go to the first pending or skipped test, and make that pass as well. When all of the tests are passing, feel free to submit.\n\nRemember that passing code is just the first step. The goal is to work towards a solution that is as readable and expressive as you can make it.\n\nPlease make your solution as general as possible. Good code doesn't just pass the test suite, it works with any input that fits the specification.\n\nHave fun!\n\n\n\n## Source\n\nInspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. [view source](http://pine.fm/LearnToProgram/?Chapter=06)\n"
},
"fresh": true,
"readme": "Please upgrade to the latest version of the exercism command-line client. See: http://cli.exercism.io",
"test_file": "PLEASE_UPGRADE.txt",
"tests": "Please upgrade to the latest version of the exercism command-line client. See: http://cli.exercism.io"
},
{
"track": "ruby",
"slug": "word-count",
"files": {
"word_count_test.rb": "require 'minitest/autorun'\nrequire_relative 'phrase'\n\nclass PhraseTest < MiniTest::Unit::TestCase\n\n def test_count_one_word\n phrase = Phrase.new(\"word\")\n counts = {\"word\" => 1}\n assert_equal counts, phrase.word_count\n end\n\n def test_count_one_of_each\n skip\n phrase = Phrase.new(\"one of each\")\n counts = {\"one\" => 1, \"of\" => 1, \"each\" => 1}\n assert_equal counts, phrase.word_count\n end\n\n def test_count_multiple_occurrences\n skip\n phrase = Phrase.new(\"one fish two fish red fish blue fish\")\n counts = {\"one\" => 1, \"fish\" => 4, \"two\" => 1, \"red\" => 1, \"blue\" => 1}\n assert_equal counts, phrase.word_count\n end\n\n def test_count_everything_just_once\n skip\n phrase = Phrase.new(\"all the kings horses and all the kings men\")\n phrase.word_count # count it an extra time\n counts = {\n \"all\" => 2, \"the\" => 2, \"kings\" => 2, \"horses\" => 1, \"and\" => 1, \"men\" => 1\n }\n assert_equal counts, phrase.word_count\n end\n\n def test_ignore_punctuation\n skip\n phrase = Phrase.new(\"car : carpet as java : javascript!!&@$%^&\")\n counts = {\"car\" => 1, \"carpet\" => 1, \"as\" => 1, \"java\" => 1, \"javascript\" => 1}\n assert_equal counts, phrase.word_count\n end\n\n def test_handles_cramped_lists\n skip\n phrase = Phrase.new(\"one,two,three\")\n counts = {\"one\" => 1, \"two\" => 1, \"three\" => 1}\n assert_equal counts, phrase.word_count\n end\n\n def test_include_numbers\n skip\n phrase = Phrase.new(\"testing, 1, 2 testing\")\n counts = {\"testing\" => 2, \"1\" => 1, \"2\" => 1}\n assert_equal counts, phrase.word_count\n end\n\n def test_normalize_case\n skip\n phrase = Phrase.new(\"go Go GO\")\n counts = {\"go\" => 3}\n assert_equal counts, phrase.word_count\n end\n\n def test_with_apostrophes\n skip\n phrase = Phrase.new(\"First: don't laugh. Then: don't cry.\")\n counts = {\"first\"=>1, \"don't\"=>2, \"laugh\"=>1, \"then\"=>1, \"cry\"=>1}\n assert_equal counts, phrase.word_count\n end\nend\n",
"README.md": "# Word Count\n\nWrite a program that given a phrase can count the occurrences of each word in that phrase.\n\nFor example for the input `\"olly olly in come free\"`\n\n```plain\nolly: 2\nin: 1\ncome: 1\nfree: 1\n```\n\n\n\n## Source\n\nThe golang tour [view source](http://tour.golang.org)\n"
},
"fresh": false,
"readme": "Please upgrade to the latest version of the exercism command-line client. See: http://cli.exercism.io",
"test_file": "PLEASE_UPGRADE.txt",
"tests": "Please upgrade to the latest version of the exercism command-line client. See: http://cli.exercism.io"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"assignments": [
{
"track": "ruby",
"slug": "bob",
"files": {
"bob_test.rb": "require 'minitest/autorun'\n\nbegin\n require_relative 'bob'\nrescue LoadError => e\n eval(\"\\\"#{DATA.read}\\n\\\"\").split(\"\\n.\\n\").each_with_index do |s,i|\n if i > 0\n puts \"\\t--- press enter to continue ---\"\n gets\n end\n puts \"\\n\\n\", s, \"\\n\\n\\n\"\n end\n exit!\nend\n\nclass TeenagerTest < MiniTest::Unit::TestCase\n attr_reader :teenager\n\n def setup\n @teenager = ::Bob.new\n end\n\n def test_stating_something\n assert_equal 'Whatever.', teenager.hey('Tom-ay-to, tom-aaaah-to.')\n end\n\n def test_shouting\n skip\n assert_equal 'Woah, chill out!', teenager.hey('WATCH OUT!')\n end\n\n def test_shouting_gibberish\n skip\n gibberish = ('A'..'Z').to_a.shuffle[0,10].join\n assert_equal 'Woah, chill out!', teenager.hey(gibberish)\n end\n\n def test_asking_a_question\n skip\n assert_equal 'Sure.', teenager.hey('Does this cryogenic chamber make me look fat?')\n end\n\n def test_asking_a_numeric_question\n skip\n assert_equal 'Sure.', teenager.hey('You are, what, like 15?')\n end\n\n def test_asking_gibberish\n skip\n gibberish = ('a'..'z').to_a.shuffle[0,10].join\n assert_equal 'Sure.', teenager.hey(\"#{gibberish}?\")\n end\n\n def test_talking_forcefully\n skip\n assert_equal 'Whatever.', teenager.hey(\"Let's go make out behind the gym!\")\n end\n\n def test_using_acronyms_in_regular_speech\n skip\n assert_equal 'Whatever.', teenager.hey(\"It's OK if you don't want to go to the DMV.\")\n end\n\n def test_forceful_questions\n skip\n assert_equal 'Woah, chill out!', teenager.hey('WHAT THE HELL WERE YOU THINKING?')\n end\n\n def test_shouting_numbers\n skip\n assert_equal 'Woah, chill out!', teenager.hey('1, 2, 3 GO!')\n end\n\n def test_only_numbers\n skip\n assert_equal 'Whatever.', teenager.hey('1, 2, 3')\n end\n\n def test_question_with_only_numbers\n skip\n assert_equal 'Sure.', teenager.hey('4?')\n end\n\n def test_shouting_with_special_characters\n skip\n assert_equal 'Woah, chill out!', teenager.hey('ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!')\n end\n\n def test_shouting_with_no_exclamation_mark\n skip\n assert_equal 'Woah, chill out!', teenager.hey('I HATE YOU')\n end\n\n def test_statement_containing_question_mark\n skip\n assert_equal 'Whatever.', teenager.hey('Ending with ? means a question.')\n end\n\n def test_prattling_on\n skip\n assert_equal 'Sure.', teenager.hey(\"Wait! Hang on. Are you going to be OK?\")\n end\n\n def test_silence\n skip\n assert_equal 'Fine. Be that way!', teenager.hey('')\n end\n\n def test_prolonged_silence\n skip\n silence = \" \" * rand(1..10)\n assert_equal 'Fine. Be that way!', teenager.hey(silence)\n end\n\n def test_on_multiple_line_questions\n skip\n assert_equal 'Whatever.', teenager.hey(%{\nDoes this cryogenic chamber make me look fat?\nno})\n end\nend\n__END__\n\n######## ######## ######## ####### ########\n## ## ## ## ## ## ## ## ##\n## ## ## ## ## ## ## ## ##\n###### ######## ######## ## ## ########\n## ## ## ## ## ## ## ## ##\n## ## ## ## ## ## ## ## ##\n######## ## ## ## ## ####### ## ##\n\n\n#{e.backtrace.first} #{e.message}\n\nWelcome to your first ruby Exercism exercise! This is your first error message.\n.\nFirst it tells you the name of the file where the error is occurring:\n\n bob_test.rb\n.\nThen it tells you which line that error is on:\n\n bob_test.rb:4\n.\nAfter that, it tells you the name of the method where the error is occurring:\n\n in `require_relative'\n.\nNext, it tells you exactly what the error is:\n\n #{e.message.split('--').first}\n.\nFinally, it tells you which file is missing:\n\n #{e.message.split('--').last}\n.\nSo the error is there on line 4 of this file (bob_test.rb). What's on line 4?\n\n require_relative 'bob'\n\nWe are trying to require the file, and it isn't there.\n.\nYou can fix the problem by creating an empty file named bob.rb inside\nof the ruby/bob directory.\n\nThen run this test again (ruby bob_test.rb). Make all the tests pass,\nand submit your solution (exercism submit bob.rb).\n\nMore instructions are in README.md in this directory. Good luck!\n",
"README.md": "# Bob\n\nBob is a lackadaisical teenager. In conversation, his responses are very limited.\n\nBob answers 'Sure.' if you ask him a question.\n\nHe answers 'Woah, chill out!' if you yell at him.\n\nHe says 'Fine. Be that way!' if you address him without actually saying anything.\n\nHe answers 'Whatever.' to anything else.\n\n## Instructions\n\nRun the test file, and fix each of the errors in turn. When you get the first test to pass, go to the first pending or skipped test, and make that pass as well. When all of the tests are passing, feel free to submit.\n\nRemember that passing code is just the first step. The goal is to work towards a solution that is as readable and expressive as you can make it.\n\nPlease make your solution as general as possible. Good code doesn't just pass the test suite, it works with any input that fits the specification.\n\nHave fun!\n\n\n\n## Source\n\nInspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. [view source](http://pine.fm/LearnToProgram/?Chapter=06)\n"
},
"fresh": true,
"readme": "Please upgrade to the latest version of the exercism command-line client. See: http://cli.exercism.io",
"test_file": "PLEASE_UPGRADE.txt",
"tests": "Please upgrade to the latest version of the exercism command-line client. See: http://cli.exercism.io"
}
]
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.