Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Try Ruby lessons are no longer abruptly ended.

I managed to convert most of the lessons from TryRuby.org over to Try
Ruby within Hackety. I also made one or two small changes and additions
of my own.
  • Loading branch information...
commit 3c88b576f6cde8965f40ac777b062e2f0e234a93 1 parent 8b943b8
@steveklabnik steveklabnik authored
View
343 h-ety-h/console.rb
@@ -33,9 +33,13 @@ def code txt; @lesson.code txt, :stroke => "#000", :fill => "#FF6" end
def prompt txt; @lesson.code txt, :stroke => "#EEE", :fill => "#703" end
def check code, answer, output
+ debug("checking:")
+ debug("Code: " + code.to_s)
+ debug("answer: " + answer.to_s)
+ debug("output: " + output.to_s)
return unless @match
- return if @match[0] and code !~ @match[0]
- return if @match[2] and output !~ @match[2]
+ debug("hey") || return if @match[0] and code !~ @match[0]
+ debug("ho") || return if @match[2] and output !~ @match[2]
case answer when @match[1]
unless help(@bookmark[0], @bookmark[1] + 1)
help(@bookmark[0] + 1, 0)
@@ -229,7 +233,7 @@ def help chap = 1, page = 0
@lesson.clear do
subtitle "Ready, Aim"
para "The square brackets you just used are very common in Ruby. ",
- "Remember, you typed: ", prompt("poem['toast'] = 'honeydew'"),
+ "Remember, you typed: ", code("poem['toast'] = 'honeydew'"),
". That box with the word ", em("toast"), " has a square bracket ",
" on each side, see?"
para "The two brackets are like sights used to line up a target. ",
@@ -416,11 +420,340 @@ def help chap = 1, page = 0
prompt('Dir.entries "/"')
end
@match = [/entries/, Array]
+ when 2
+ @lesson.clear do
+ subtitle "The Private Collection of Dr. Dir"
+ para "You've just listed out everything in the top directory. The",
+ " root directory, indicated by a single slash."
+ para "So, what is the ", code('Dir.entries'), " method? Well, it's",
+ " just a method, right?", code('entries'), " is a method called on",
+ " the ", code('Dir'), " variable. And ", code('Dir'), " has a ",
+ " collection of methods for checking out file directories."
+ para "One other little thing we haven't really talked about openly. ",
+ "Method arguments, highlighted in green."
+
+ item code('Dir.entries "/"'), ": Anything listed after a method",
+ " is considered an attachment."
+ item code('print poem'), ": See, ", code('print'), " is an ordinary",
+ " method. And the poem is attached. To be printed."
+ item code('print "pre", "event", "ual", "ism"'), " has several",
+ " arguments, with commas between them."
+ para "To list just the text files in that directory: ",
+ prompt('Dir["*.txt"]')
+ end
+ @match = [/\*\.txt/, Array]
+ when 3
+ @lesson.clear do
+ subtitle "Come, Read Comics With Me"
+ para "The ", code("Dir[]"), " method is like ", code("entries"), " but you",
+ " search for files with wildcard characters. Here, we see those square",
+ " brackets again! Notice how they still mean, \"I am looking for _____?\""
+ para "More specifically: \"I am looking for files which end with ", code('.txt'), ".\""
+ para "Let's crack open this comics file, then. Here's the way: "
+ para prompt('print File.read("comics.txt")')
+ end
+ @match = [nil, nil, /Achewood.+/]
+ when 4
+ @lesson.clear do
+ subtitle "Mi Comicas, Tu Comicas"
+ para "All right! We can start to use files to store things. This is",
+ " great because normally when we exit Ruby, all our variables will",
+ " be gone. Ruby, by itself, forgets these things. But if we save",
+ " things in files, we can read those files in future Ruby escapades."
+ para "Hey, and guess what? The ", code("Home"), " directory is yours! I gave it to you! I am generous! Let's make a copy of the comics file."
+ para "You'll want to: ", prompt("FileUtils.copy('comics.txt', 'Home/comics.txt')")
+ para em("If you've already created the file, use File.delete('Home/comics.txt') to trash it.")
+ end
+ @match = [/FileUtils/, nil]
+ when 5
+ @lesson.clear do
+ subtitle "Your Own Turf"
+ para "Okay, you've got a copy. Check it: ",
+ code('Dir["Home/*.txt"]')
+ para "To add your own comic to the list, let's open the file in ",
+ strong('append'), " mode."
+ para "Do it like this:"
+ para prompt('File.open("Home/comics.txt", "a") do |f|'),
+ "."
+ para "Then press Enter. Your prompt will change to two dots. Then this:"
+ para prompt('f << "Cat and Girl: http://catandgirl.com/\n"')
+ para "And another Enter. Finally, an ", prompt("end"), " should do it!"
+ end
+ @match = [nil, File]
+ end
+ when 6
+ Dir.chdir(File.join(HH::HOME, 'root'))
+ case page
+ when 0
+ @lesson.clear do
+ subtitle "Hallo, Who's There? And Summary #5 Waves Its Hat!"
+ para "Well done, well done, well done, well done! Truly, truly, ",
+ "truly, truly, truuuuuuuuly!"
+ para "Here's the last few minutes of your life in review:"
+ item strong('Files.'), "What more can be said? Lots of methods for",
+ "editing files and lookin around in directories."
+ item strong('Arguments.'), "Arguments are a list of things sent into",
+ "a method. With commas between."
+ item "We also spoke about ", strong('do'), " and ", strong('end'),
+ " which are another way to make a block."
+ para "You totally know how to use Ruby now. I mean you've got down the",
+ " essentials. You just need to keep learning more methods and",
+ " try out more complex blocks."
+ para "But there's one side of Ruby we haven't settled. Making your own",
+ " methods and classes. "
+ para em('Ahem!'), " Let's get it over with then."
+ para "Try this: "
+ item prompt('def say_hello( name )')
+ item prompt(' puts "Hello, " + name')
+ item prompt('end')
+ end
+ @match = [//,nil,//]
+ when 1
+ @lesson.clear do
+ subtitle "In Ruby, Def Leppard Means Define Leppard (a Method)!"
+ para "Hey, okay, you done it. You're making your own method. You started",
+ " with ", code('def'), ", followed by the name of the method."
+ para "And a list of arguments which the method will need. This isn't too",
+ " scary and dangerous!"
+ para "now try it out:"
+ para prompt('say_hello("Steve")')
+ end
+ @match = [/say_hello/, nil, /Hello, /]
+ when 2
+ @lesson.clear do
+ subtitle "Once again, with feeling!"
+ para "Awesome! Once you make your own methods, you can call them just",
+ " like you would any other method."
+ para "That was a pretty simple method. Let's try a bigger one, with",
+ " our comics.txt file."
+ item prompt('def load_comics( path )')
+ item prompt(' comics = {}')
+ item prompt(' File.foreach(path) do |line|')
+ item prompt(' name, url = line.split(\': \')')
+ item prompt(' comics[name] = url.strip')
+ item prompt(' end')
+ item prompt(' comics')
+ item prompt('end')
+ end
+ @match = [/load_comics/, nil, //]
+ when 3
+ @lesson.clear do
+ subtitle "The Ripened Fruit of Your Own Creation"
+ para "A new method is born. Let us use it: ",
+ prompt("comics = load_comics('comics.txt')")
+ para em('If you have a problem, you might have mistyped. Use the '), code('back'),
+ em(" command and try again.")
+ end
+ @match = [/load_comics/, Hash]
+ when 4
+ @lesson.clear do
+ subtitle "Hey, Cool, a Comics Thing"
+ para "In your Ruby window above, look at the code you've typed for the ",
+ code('load_comics'), " method. What is happening? You're passing in the",
+ code('path'), " variable and you're getting back the ",
+ code('comics'), " variable. Ruby lets the ",
+ code('comics'), " hash trickle out the end of the method."
+ para "A number of methods were used to get the job done. See if you can spot them."
+ item strong('File.foreach'), " is a method which opens a file and ",
+ "hands each line to the block. The ",
+ code('line'), " variable inside the ", code('do...end'),
+ " block took turns with each line in the file."
+ item strong('split'), " is a method for strings, which breaks the",
+ " string up into an array. An axe is laid on the colon and the",
+ " line is chopped in half, giving us the ", code('url'),
+ " and ", code('name'),' for each comic.'
+ item strong('strip'), " removes extra spaces around the name. Just in case."
+ para "Right on. Bravo. You've got the comics in a Ruby hash. But what now?"
+ " What good is this really? What if you needed more than just a URL?"
+ para "To glimpse into the future, try this: ",
+ prompt("{ }.class")
+ end
+ @match = [/class/, Class]
+ end
+ when 7
+ case page
+ when 0
+ @lesson.clear do
+ subtitle "Summary #6 Which Means You've Come So Far"
+ para "You're a level six Ruby cleric. I mean what a great job you've done. Let's review:"
+ para "So what could possibly be next? What could you possibly have to learn now?",
+ "Ha, this is the best part. You've come such a long way that we're going",
+ " to uncover classes. For two more short lessons and you're done."
+ para "Earlier, we created a hash like this: ", prompt('Hash.new'), " Try it."
+ end
+ @match = [/Hash/, Hash]
+ when 1
+ @lesson.clear do
+ subtitle "Not a School Class, a Working Class"
+ para "You see, the empty curly braces ", code('{}'), " is a shortcut for ",
+ code('Hash.new'), ". The ", code('new'), " method is used to make objects ",
+ " of a certain class. (Think \"class\" as in \"working class\"; a specific ",
+ "group of objects which are similar, have the same jobs, the same shirts.)"
+ para "Ask yourself this: ", em('How would I make a blog in Ruby?')
+ para " Where would you start? Well, you might store your blog entries in a ",
+ "file, right? But how would you keep track of the title of the entry and ",
+ "the time it was posted? And when you loaded the file, how would it look ",
+ "in Ruby? Would it be a Hash? Or an Array? Or an Array of Arrays? Or something else?"
+ para "I really think you'll want to use a class. You are already familiar with ",
+ "many classes: ", code('Hash'), ", ", code('Array'), ", ", code('String'), "."
+ para "Let's make a new class: "
+ item prompt('class BlogEntry')
+ item prompt('end')
+ end
+ @match = [/class BlogEntry/, nil]
+ when 2
+ @lesson.clear do
+ subtitle "The Stuff Blogs are Made of"
+ para "You've opened up a new ", code('BlogEntry'), " class. What is your blog entry ",
+ "made of? A title, sure. Also, a time when the entry was posted. The full text of the entry."
+ para "We'll do a mood setting, too, just like LiveJournal. "
+ para "Okay, so you know how to make a class. Let's try that again, and :"
+ item prompt('class BlogEntry')
+ item prompt(' attr_accessor :title, :time, :fulltext, :mood')
+ item prompt('end')
+ end
+ @match = [/BlogEntry/, nil]
+ when 3
+ @lesson.clear do
+ subtitle "Accessors Are the Dangling Limbs"
+ para "Hey, good class, man. You've got a new ", code('BlogEntry'),
+ " class. To start an entry: "
+ item prompt('entry = BlogEntry.new'), "."
+ para "In the class definition, you used a method called ",
+ code('attr_accessor'), ". There are many ", strong('attr'), "ibute ",
+ "methods like this which add little settings to classes. These ",
+ "attributes are just variables attached to a class."
+ para "Think of it this way. A class is like a person. That star-shaped ",
+ "human thing out there. And the attributes are the dangling limbs, the ",
+ " different parts that make up a body."
+ para "To set the title of your entry: "
+ item prompt('entry.title = "Today Mt. Hood Was Stolen!"')
+ end
+ @match = [/entry/, String]
+ when 4
+ @lesson.clear do
+ subtitle "An Object, That Neat Little Package"
+ para "Go ahead and set the post time:"
+ item prompt('entry.time = Time.now')
+ para "And the mood:"
+ item prompt('entry.mood = :sick')
+ para "And the post itself:"
+ item prompt('entry.fulltext = "I can\'t believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away in his Cadillac Seville very nonchalant!!"')
+ para "To see all your settings, just type at the prompt: "
+ item prompt('entry'), "."
+ end
+ @match = [/^entry$/, Object]
+ when 5
+ @lesson.clear do
+ subtitle "Quickening it Up"
+ para "Cool, your blog is awesome. Hey, let's make things a bit easier on you.",
+ "You're not going to want to set the time like that every time you post.",
+ "You just want to type in the title and the entry and the mood quickly, right?"
+ para "Let's add an ", code('initialize'), " method."
+ item prompt('class BlogEntry')
+ item prompt(' def initialize( title, mood, fulltext )')
+ item prompt(' @time = Time.now')
+ item prompt(' @title, @mood, @fulltext = title, mood, fulltext')
+ item prompt(' end')
+ item prompt('end')
+ para "Once you've got that typed in, try making a new entry: ",
+ prompt('BlogEntry.new')
+ end
+ @match = [/BlogEntry/, nil, /method needs a bit more/]
+
+ when 6
+ @lesson.clear do
+ subtitle "You've Taught Your Blog to Reject Worthless Things"
+ para "Did you see how inside the class we used the at-symbols? Like this: ",
+ code('@time = Time.now')
+ para 'Outside the class, we use accessors: ',
+ code('entry.time = Time.now'),
+ "But inside we use ", em('instance variables'), ": ", code('@time = Time.now'),
+ "They're the exact same thing, but expressed in two different places of your program."
+ para "Your blog now needs a title, a mood and a post in order to work. When a new ",
+ code('BlogEntry'), " is created, the ", code('initialize'),
+ "method is used to check for any arguments to ", code('new'), ". Uh, we need three arguments!"
+ para "Try it again with all three."
+ para prompt('entry2 = BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am never going back to that mountain and I hope a giraffe steals it." )')
+ end
+ @match = [/entry/, Object]
+ end
+ when 8
+ case page
+ when 0
+ @lesson.clear do
+ subtitle 'A Giraffe Has Not Stolen Summary #7'
+ para "Aha, you're here. And all in one piece. We're still going to make",
+ " your blog real, but until then, let's review, okay?"
+ item strong('Classes.'), " Everything in Ruby is some kind of object. ",
+ "Classes explain how a certain object works. For example, you",
+ " made a few blog entry objects and these objects are explained in the ",
+ code('BlogEntry'), " class. In other words: you call them BlogEntry objects."
+ item strong('Accessors'), " are variables attached to an object which can be used ",
+ em('outside'), " the object. (", code('entry.time = Time.now'), ")"
+ item strong('Instance variables'), " are the same variables you're using for accessors",
+ " when ", em('inside'), " the object. Like in a method definition. (",
+ code('@time = Time.now'), ")"
+ para "Okay, let's wrap things up, kid. Here's the last chapter of the GRIPPING epic",
+ " story of Try Ruby! Now that you've got a taste of how it all works, how",
+ " are you going to use it around the house and in your grocer's freezer?"
+ para "Let's finish your blog. You have blog entries, but no actual blog."
+ para "Put the entries into an array: ", code('blog = [entry, entry2]')
+ end
+ @match = [/blog/, Array]
+ when 1
+ @lesson.clear do
+ subtitle "It's All About Combining Things"
+ para "Some beautiful things can be done with the simple parts of Ruby, especially",
+ " when you combine them together into new things. Here we've got a blog",
+ " made of an array of classes. And, actually, Ruby really does good with",
+ " this kind of creature."
+ para "Here's a few things you can do with your array blog:"
+ item "You'll want to sort your entries from newest to oldest. You can do this with: ",
+ code('blog.sort_by { |entry| entry.time }.reverse')
+ item 'If you want to search your blog for anything related to "cadillac": ',
+ code('blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }'),
+ "the slashy ", code('/giraffe/i'), " is a Regexp object, used for matching words."
+ item "Add new entries with ",
+ code('blog << new_entry')
+ para "You can browse a list of all Ruby's built-in methods at ", strong('http://ruby-doc.org/core/'), " ."
+ para "One ", em('really'), " useful method (I probably use this more than anything else) is ",
+ code('map'), ". Type: ",
+ prompt('blog.map { |entry| entry.mood }')
+ end
+ @match = [/mood/, Array]
+ when 2
+ @lesson.clear do
+ subtitle "That Map's not on Google"
+ para "Okay, actually, Enumerable#map is.",
+ "(That means the ", code('map'), " method of the ", code('Enumerable'), " class, by the way.)"
+ para "Anyway, it's called ", code('map'), " because you're mapping one Array to another. ",
+ "See how you called that method on an Array, and you got one back? This map is showing the way",
+ " from each BlogEntry to each mood."
+ para "What other things would you want to do with a list of things? How about adding them together?"
+ para "A map won't work for that, because we need to come up with one answer, not a list of them!",
+ " For this job, we'll need ", code('inject'), ". Try it:"
+ para prompt('[1, 2, 3, 4, 5].inject {|sum, n| sum + n }')
+ end
+ @match = [/inject/, Fixnum]
+ when 3
+ @lesson.clear do
+ subtitle "Shove those numbers in there!"
+ para "The ", code('inject'), " method takes a block with two arguments, ",
+ "and gives back a single answer! We keep shoving elements of the array ",
+ "into the block over and over again, and end up with a Last Element Standing."
+ para "In this case, we've used + to add them all together. Groovy!"
+ para prompt('[1, 2, 3, 4, 5].inject {|sum, n| sum + n }')
end
+ @match = [/inject/, Fixnum]
+ end
when 9
@lesson.clear do
- subtitle "At That, The Lessons Come To An Abrupt Conclusion"
- para "No further instructions are complete."
+ subtitle "Summary #8, The Hey-Relax-You-Did-Good Summary"
+ para "You really deserve a double-layer cake with double-double frosting and a",
+ " guy playing one of those guitars that's a double guitar. I mean you",
+ " finished, you really did! No doubt about it, you're a certified",
+ " red-blooded smartiac!"
end
@match = nil
end
View
5 h-ety-h/editor.rb
@@ -290,7 +290,8 @@ def onkey(k)
end
when :control_v, :alt_v, :shift_insert
handle_text_insertion(self.clipboard) if self.clipboard
- when :control_z, :alt_z
+ when :control_z
+ debug("undo!")
undo_command
when :control_y, :alt_Z, :shift_alt_z
redo_command
@@ -433,4 +434,4 @@ def delete_text pos, len
@t.cursor = :marker
#update_text
end
-end
View
0  root/Home/.gitignore
No changes.
Please sign in to comment.
Something went wrong with that request. Please try again.