Skip to content

Stepfile-style ruby only curriculum #140

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
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
43 changes: 43 additions & 0 deletions lib/step.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ class Step < Erector::Widget
.deploying>h1 {
background-color: #B0DEE7;
}
.further-reading>h1 {
background-color: rgb(135, 229, 242);
}

table.bordered td,
table.bordered tr {
border-style: solid;
border-width: 1px;
border-color: black;
padding-left: 5px;
padding-right: 5px;
}

.requirements>h1 {
background-color: #93B5DA;
Expand Down Expand Up @@ -135,6 +147,13 @@ class Step < Erector::Widget
}
}

.in_file > pre {
border: 4px solid #dde;
@include border-radius(4px);
background-color: gray;
color: white;
}

.result > pre {
border: 4px solid #dde;
@include border-radius(4px);
Expand Down Expand Up @@ -321,6 +340,7 @@ def todo todo_text
## special

TERMINAL_CAPTION = "Type this in the terminal:"
IRB_CAPTION = "Type this in irb:"
RESULT_CAPTION = "Expected result:"
FUZZY_RESULT_CAPTION = "Approximate expected result:"

Expand All @@ -330,6 +350,29 @@ def console msg
pre msg
end
end

def irb msg
div :class => "console" do
span IRB_CAPTION
pre msg
end
end

def type_in_file filename, msg
div do
span "Type this in the file #{filename}:"
source_code :ruby, msg
end
end

def further_reading
div :class => "further-reading" do
h1 "Further Reading"
blockquote do
yield
end
end
end

def result text
div :class => "result" do
Expand Down
93 changes: 93 additions & 0 deletions sites/ruby/arrays.step
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
goals do
goal "Make some arrays and do stuff with them"
goal "Retrieve data from arrays"
end

step do
irb <<IRB
fruits = ["kiwi", "strawberry", "plum"]
IRB
message 'An array is a list of things in square brackets, separated by commas.'
message 'We generally call the individual things in an array **elements**.'
irb <<-IRB
things = [5, 'tree', 19.5]
things.length
IRB
message 'An array can contain all sorts of things, not just strings.'
message '`length` is a method that tells you how many **elements** are in an array.'
irb <<-IRB
empty_array = []
empty_array.length
IRB
message 'The simplest kind of array is the empty array.'
end

step do
irb <<IRB
fruits[0]
fruits[1]
fruits[2]
IRB
message 'Array elements are stored in order. You can retrieve them by using the square brackets to access them by their **index**.'
message 'Arrays are ordered: elements remain in the same order they started in.'
message 'Ruby starts counting at zero: the first element is `fruits[0]`.'
irb <<IRB
fruits.first
fruits.last
IRB
message 'Ruby gives us some helpful ways to get the first and last element from an array.'
end

step do
irb <<IRB
['salt'] + ['pepper']
IRB
message 'Arrays can be added together with the plus operator.'
irb <<IRB
fruits + ['mango']
fruits
IRB
message 'The plus operator doesn\'t modify the existing array, it makes a new one. How could you write that last piece of code to also modify the fruits array?'
end

step do
irb <<IRB
fruits = ["kiwi", "strawberry", "plum"]
fruits.push('apple')
fruits.pop()
IRB
message 'Ruby has many methods for modifying arrays. What did these two methods do?'
end

explanation do
message "Arrays are used whenever you need to work with a large group of similar items."
message 'A short list of methods for Array:'
table class: 'bordered' do
tr do
td 'length'
td 'how long is this array (how many elements)'
end
tr do
td 'first'
td 'get the first element of the array (same as array[0])'
end
tr do
td 'last'
td 'get the last element of the array (same as array[-1])'
end
tr do
td 'push'
td 'add a new element to the end of the array'
end
tr do
td 'pop'
td 'remove (and return) the element at the end of the array'
end
end
end

further_reading do
a "Ruby's documentation for Array", href: 'http://www.ruby-doc.org/core-1.9.3/Array.html'
end

next_step "hashes"
76 changes: 76 additions & 0 deletions sites/ruby/command_line.step
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
goals do
goal "Learn about the command line"
goal "Make a new directory"
goal "Browse some directories on your computer"
goal do
rawtext md2html("Learn the commands `pwd`, `mkdir`, `ls`, `cd` and `man`")
end
end

step do
message 'Open up a command line application on your computer. On Macs, this program is called Terminal. On Windows, you might want to use the "Command Line With Ruby and Rails" shortcut that came with RailsInstaller.'
console "pwd"
message '`pwd` means "print working directory". It shows you what **directory** you\'re currently in. Directories are also often called **folders**.'
message '`pwd` can help orient you in the command line if you get lost somewhere in your computer.'
end

step do
irb 'mkdir railsbridge_ruby'
message '`mkdir` means **m**ake **d**irectory. You use mkdir when you want to create a new directory.'
message 'The command line is just one way of manipulating the files on your computer. Try to find the new directory you created in Finder or Windows Explorer.'
message 'If you get an error saying the directory already exists, maybe someone did these steps on your computer before. Don\'t fret.'
end

step do
console 'cd railsbridge_ruby'
message '`cd` means **c**hange **d**irectory. You use cd when you want to move from the current directory into some other directory.'
end

step do
message "If you're on a Mac or Linux computer:"
console 'cd ~'
message "`~` indicates your **home directory**, a directory owned by the account currently logged in to the computer. Your home directory might be something like `/home/sparklepants` (Linux) or `/Users/saucyfrank` (Mac)"
message "Practice moving in and out of various directories. Remember that you can always get back to your home with `cd ~`."
end

step do
console 'ls'
message '`ls` stands for **list**, and shows the contents of the current directory.'
message 'Since you moved back to your Home directory, you should see the newly-created railsbridge_ruby directory in the output of `ls`.'
end

step do
console 'man ls'
message '`man` stands for **manual** and shows you the documentation for a command. This can include various options used to run the command in different ways.'
message "If you see a colon at the bottom of your terminal when viewing a man page, it means you're in a **pager**. Pagers are special programs for showing text that spans multiple pages. You can press the up and down arrows to page through the text, or type `q` to exit."
end

explanation do
message "The command line is an essential tool for computer programmers. While daunting at first, it offers great flexibility in moving around your computer and manipulating files."
message "There are many, many, many more commands available on the command line than what we've seen here, but these are enough to get you going."
message 'Command summary:'
table class: 'bordered' do
tr do
td 'pwd'
td 'print working directory'
td 'print the full path to your current directory'
end
tr do
td 'ls'
td 'list directory'
td 'display the contents of the current directory'
end
tr do
td 'cd [directory]'
td 'change directory'
td 'make this directory the current directory'
end
tr do
td 'man [cmd]'
td 'manual'
td "show the manual for this command. press 'q' to quit."
end
end
end

next_step "irb"
88 changes: 88 additions & 0 deletions sites/ruby/conditionals.step
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
goals do
goal do
rawtext(md2html('Use `gets` to get input from the user of your program.'))
end
goal 'Use a conditional statement to execute a branch of code only some of the time.'
end

step do
message 'Create a new file called conditionals_test.rb'
type_in_file 'conditionals_test.rb', <<-'CONTENTS'
print "How many apples do you have? > "
apple_count = gets.to_i
puts "You have #{apple_count} apples."
CONTENTS
console 'ruby conditionals_test.rb'
message 'When prompted, type in a number of apples and press enter.'
message "`print` is like `puts` but doesn't make a new line after printing."
message "`gets`, or **get** **s**tring, pauses your program and waits for the user to type something and hit the enter key. It then returns the value back to your program and continues execution. Since the user could have typed anything ('banana', '19.2', '<<!!@@') we use to_i to ensure what comes out is an integer. If the user didn't type a valid integer, `to_i` returns `0`."
end

step do
message 'Continuing on from the end of conditionals_test.rb...'
type_in_file 'conditionals_test.rb', <<-'CONTENTS'
if apple_count > 5
puts "Lots of apples!"
else
puts 'Not many apples...'
end
CONTENTS
console 'ruby conditionals_test.rb'
message 'The `if ... else ... end` construct is a way of changing which lines of your program get executed depending on your data.'
message 'Try running the program with different values for apple_count to see each side of the conditional get executed.'
end

step do
message 'What goes after the `if` is any expression that returns a **boolean**, (the values `true` or `false`). Here\'s some more expressions that return `true` or `false`:'
irb <<-IRB
15 < 5
10 == 12
'foo' != 'bar'
IRB
irb <<-IRB
'sandwich'.end_with?('h')
'sandwich'.end_with?('z')
[1,2,3].include?(2)
[1,2,3].include?(9)
IRB
message 'Many methods return `true` or `false` as well. By convention, methods in Ruby that return booleans end with a question mark.'
end

step do
message 'You can nest a conditional in a loop, as well.'
message 'Create a new file called conditional_loops.rb'
type_in_file 'conditional_loops.rb', <<-'CONTENTS'
fruits = ['apple', 'pear', 'apricot']
fruits.each do |fruit|
if fruit.start_with?('a')
puts "#{fruit} begins with the letter a."
end
end
CONTENTS
console 'ruby conditional_loops.rb'
message "Try changing this conditional so it only prints fruits with at least five letters in their name. Remember to change the string you're `puts`ing as well!"
end

step do
message 'Create a new file called while_loop.rb'
type_in_file 'while_loop.rb', <<-'CONTENTS'
total = 0
user_input = nil
while user_input != 'stop'
print 'Enter a number to add to the total. > '
user_input = gets.chomp
total = total + user_input.to_i
end
puts "Your final total was #{total}!"
CONTENTS
console 'ruby while_loop.rb'
message "A **while** loop continues repeating until a certain statement is false. Here, the program continually asks us for numbers until we say the string 'stop'."
message "It's easy for a while loop to get out of control! If your loop body doesn't do anything to make the **while** condition false, your loop will run forever."
end

explanation do
message "Without some kind of conditional, your program would do the same thing every time. Conditionals let you choose to do different things depending on what data you have in hand."
message 'Now that you know *conditionals*, *loops*, *arrays*, *hashes* and *strings*, you can make some pretty complicated programs!'
end

next_step 'functions'
28 changes: 28 additions & 0 deletions sites/ruby/functions.step
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
goals do
goal "Create a function"
goal "Call a function"
end

step do
message 'Create a new file called area.rb'
type_in_file 'area.rb', <<-'CONTENTS'
def circle_area(radius)
Math::PI * (radius ** 2)
end

print "What is the radius of your circle? > "
radius = gets.to_i

puts "Your circle has an area of #{circle_area(radius)}"
CONTENTS
console 'ruby area.rb'
message 'When prompted, type in a radius for your circle.'
end

explanation do
message "As your programs get more and more complicated, you'll want to group code into **functions** that can be called over and over again."
message "A **function** begins with **def**, followed by the function name. Next comes any **variables** it takes, followed by the actual body of the function. Lastly, function definitions are finished with the **end** keyword."
message "Pedantic Programmers might want to tell you that Ruby doesn't technically have **functions**, and everything in ruby is really a **method**. It is appropriate to slap these people."
end

next_step 'objects'
Loading